View Javadoc

1   package org.apache.maven.artifact.ant;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.File;
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.io.Reader;
26  import java.io.StringReader;
27  import java.io.StringWriter;
28  import java.net.MalformedURLException;
29  import java.net.URL;
30  import java.util.ArrayList;
31  import java.util.Iterator;
32  import java.util.List;
33  import java.util.Map;
34  import java.util.Properties;
35  
36  import org.apache.maven.artifact.Artifact;
37  import org.apache.maven.artifact.factory.ArtifactFactory;
38  import org.apache.maven.artifact.manager.WagonManager;
39  import org.apache.maven.artifact.repository.ArtifactRepository;
40  import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
41  import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
42  import org.apache.maven.artifact.repository.DefaultArtifactRepository;
43  import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
44  import org.apache.maven.profiles.DefaultProfileManager;
45  import org.apache.maven.profiles.ProfileManager;
46  import org.apache.maven.project.DefaultProjectBuilderConfiguration;
47  import org.apache.maven.project.MavenProject;
48  import org.apache.maven.project.MavenProjectBuilder;
49  import org.apache.maven.project.ProjectBuildingException;
50  import org.apache.maven.settings.Mirror;
51  import org.apache.maven.settings.RuntimeInfo;
52  import org.apache.maven.settings.Server;
53  import org.apache.maven.settings.Settings;
54  import org.apache.maven.settings.SettingsUtils;
55  import org.apache.maven.settings.TrackableBase;
56  import org.apache.maven.settings.io.xpp3.SettingsXpp3Reader;
57  import org.apache.maven.usability.diagnostics.ErrorDiagnostics;
58  import org.apache.maven.wagon.Wagon;
59  import org.apache.tools.ant.BuildException;
60  import org.apache.tools.ant.Project;
61  import org.apache.tools.ant.Task;
62  import org.apache.tools.ant.taskdefs.Execute;
63  import org.codehaus.classworlds.ClassWorld;
64  import org.codehaus.classworlds.DuplicateRealmException;
65  import org.codehaus.plexus.PlexusContainer;
66  import org.codehaus.plexus.PlexusContainerException;
67  import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
68  import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
69  import org.codehaus.plexus.embed.Embedder;
70  import org.codehaus.plexus.interpolation.EnvarBasedValueSource;
71  import org.codehaus.plexus.interpolation.RegexBasedInterpolator;
72  import org.codehaus.plexus.util.IOUtil;
73  import org.codehaus.plexus.util.ReaderFactory;
74  import org.codehaus.plexus.util.StringUtils;
75  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
76  
77  /**
78   * Base class for artifact tasks.
79   *
80   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
81   * @version $Id: AbstractArtifactTask.html 806929 2012-03-01 18:57:40Z hboutemy $
82   */
83  public abstract class AbstractArtifactTask
84      extends Task
85  {
86      private static final String WILDCARD = "*";
87  
88      private static final String EXTERNAL_WILDCARD = "external:*";
89  
90      private static ClassLoader plexusClassLoader;
91  
92      private File userSettingsFile;
93  
94      private File globalSettingsFile;
95  
96      private Settings settings;
97  
98      private ProfileManager profileManager;
99  
100     private PlexusContainer container;
101 
102     private Pom pom;
103 
104     private String pomRefId;
105 
106     private LocalRepository localRepository;
107 
108     protected ArtifactRepository createLocalArtifactRepository()
109     {
110         ArtifactRepositoryLayout repositoryLayout =
111             (ArtifactRepositoryLayout) lookup( ArtifactRepositoryLayout.ROLE, getLocalRepository().getLayout() );
112 
113         return new DefaultArtifactRepository( "local", "file://" + getLocalRepository().getPath(), repositoryLayout );
114     }
115 
116     /**
117      * Create a core-Maven ArtifactRepositoryFactory from a Maven Ant Tasks's RemoteRepository definition,
118      * eventually configured with authentication and proxy information.
119      * @param repository the remote repository as defined in Ant
120      * @return the corresponding ArtifactRepositoryFactory
121      */
122     protected ArtifactRepositoryFactory getArtifactRepositoryFactory( RemoteRepository repository )
123     {
124         WagonManager manager = (WagonManager) lookup( WagonManager.ROLE );
125 
126         Authentication authentication = repository.getAuthentication();
127         if ( authentication != null )
128         {
129             manager.addAuthenticationInfo( repository.getId(), authentication.getUserName(),
130                                            authentication.getPassword(), authentication.getPrivateKey(),
131                                            authentication.getPassphrase() );
132         }
133 
134         Proxy proxy = repository.getProxy();
135         if ( proxy != null )
136         {
137             manager.addProxy( proxy.getType(), proxy.getHost(), proxy.getPort(), proxy.getUserName(),
138                               proxy.getPassword(), proxy.getNonProxyHosts() );
139         }
140 
141         return (ArtifactRepositoryFactory) lookup( ArtifactRepositoryFactory.ROLE );
142     }
143 
144     protected void releaseArtifactRepositoryFactory( ArtifactRepositoryFactory repositoryFactory )
145     {
146         try
147         {
148             getContainer().release( repositoryFactory );
149         }
150         catch ( ComponentLifecycleException e )
151         {
152             // TODO: Warn the user, or not?
153         }
154     }
155 
156     /**
157      * Create a core-Maven ArtifactRepository from a Maven Ant Tasks's RemoteRepository definition.
158      * @param repository the remote repository as defined in Ant
159      * @return the corresponding ArtifactRepository
160      */
161     protected ArtifactRepository createRemoteArtifactRepository( RemoteRepository repository )
162     {
163         ArtifactRepositoryLayout repositoryLayout =
164             (ArtifactRepositoryLayout) lookup( ArtifactRepositoryLayout.ROLE, repository.getLayout() );
165 
166         ArtifactRepositoryFactory repositoryFactory = null;
167 
168         ArtifactRepository artifactRepository;
169 
170         try
171         {
172             repositoryFactory = getArtifactRepositoryFactory( repository );
173 
174             ArtifactRepositoryPolicy snapshots = buildArtifactRepositoryPolicy( repository.getSnapshots() );
175             ArtifactRepositoryPolicy releases = buildArtifactRepositoryPolicy( repository.getReleases() );
176 
177             artifactRepository = repositoryFactory.createArtifactRepository( repository.getId(), repository.getUrl(),
178                                                                              repositoryLayout, snapshots, releases );
179         }
180         finally
181         {
182             releaseArtifactRepositoryFactory( repositoryFactory );
183         }
184 
185         return artifactRepository;
186     }
187 
188     private static ArtifactRepositoryPolicy buildArtifactRepositoryPolicy( RepositoryPolicy policy )
189     {
190         boolean enabled = true;
191         String updatePolicy = null;
192         String checksumPolicy = null;
193 
194         if ( policy != null )
195         {
196             enabled = policy.isEnabled();
197             if ( policy.getUpdatePolicy() != null )
198             {
199                 updatePolicy = policy.getUpdatePolicy();
200             }
201             if ( policy.getChecksumPolicy() != null )
202             {
203                 checksumPolicy = policy.getChecksumPolicy();
204             }
205         }
206 
207         return new ArtifactRepositoryPolicy( enabled, updatePolicy, checksumPolicy );
208     }
209 
210     protected LocalRepository getDefaultLocalRepository()
211     {
212         Settings settings = getSettings();
213         LocalRepository localRepository = new LocalRepository();
214         localRepository.setId( "local" );
215         localRepository.setPath( new File( settings.getLocalRepository() ) );
216         return localRepository;
217     }
218 
219     protected synchronized Settings getSettings()
220     {
221         if ( settings == null )
222         {
223             initSettings();
224         }
225         return settings;
226     }
227 
228     private File newFile( String parent, String subdir, String filename )
229     {
230         return new File( new File( parent, subdir ), filename );
231     }
232 
233     private void initSettings()
234     {
235         if ( userSettingsFile == null )
236         {
237             File tempSettingsFile = newFile( System.getProperty( "user.home" ), ".ant", "settings.xml" );
238             if ( tempSettingsFile.exists() )
239             {
240                 userSettingsFile = tempSettingsFile;
241             }
242             else
243             {
244                 tempSettingsFile = newFile( System.getProperty( "user.home" ), ".m2", "settings.xml" );
245                 if ( tempSettingsFile.exists() )
246                 {
247                     userSettingsFile = tempSettingsFile;
248                 }
249             }
250         }
251         if ( globalSettingsFile == null )
252         {
253             File tempSettingsFile = newFile( System.getProperty( "ant.home" ), "etc", "settings.xml" );
254             if ( tempSettingsFile.exists() )
255             {
256                 globalSettingsFile = tempSettingsFile;
257             }
258             else
259             {
260                 // look in ${M2_HOME}/conf
261                 List<String> env = Execute.getProcEnvironment();
262                 for ( String var: env )
263                 {
264                     if ( var.startsWith( "M2_HOME=" ) )
265                     {
266                         String m2Home = var.substring( "M2_HOME=".length() );
267                         tempSettingsFile = newFile( m2Home, "conf", "settings.xml" );
268                         if ( tempSettingsFile.exists() )
269                         {
270                             globalSettingsFile = tempSettingsFile;
271                         }
272                         break;
273                     }
274                 }
275             }
276         }
277 
278         Settings userSettings = loadSettings( userSettingsFile );
279         Settings globalSettings = loadSettings( globalSettingsFile );
280 
281         SettingsUtils.merge( userSettings, globalSettings, TrackableBase.GLOBAL_LEVEL );
282         settings = userSettings;
283 
284         if ( StringUtils.isEmpty( settings.getLocalRepository() ) )
285         {
286             String location = newFile( System.getProperty( "user.home" ), ".m2", "repository" ).getAbsolutePath();
287             settings.setLocalRepository( location );
288         }
289 
290         WagonManager wagonManager = (WagonManager) lookup( WagonManager.ROLE );
291         wagonManager.setDownloadMonitor( new AntDownloadMonitor() );
292         if ( settings.isOffline() )
293         {
294             log( "You are working in offline mode.", Project.MSG_INFO );
295             wagonManager.setOnline( false );
296         }
297         else
298         {
299             wagonManager.setOnline( true );
300         }
301     }
302 
303     private Settings loadSettings( File settingsFile )
304     {
305         Settings settings = null;
306         try
307         {
308             if ( settingsFile != null )
309             {
310                 log( "Loading Maven settings file: " + settingsFile.getPath(), Project.MSG_VERBOSE );
311                 settings = readSettings( settingsFile );
312             }
313         }
314         catch ( IOException e )
315         {
316             log( "Error reading settings file '" + settingsFile + "' - ignoring. Error was: " + e.getMessage(),
317                  Project.MSG_WARN );
318         }
319         catch ( XmlPullParserException e )
320         {
321             log( "Error parsing settings file '" + settingsFile + "' - ignoring. Error was: " + e.getMessage(),
322                  Project.MSG_WARN );
323         }
324 
325         if ( settings == null )
326         {
327             settings = new Settings();
328             RuntimeInfo rtInfo = new RuntimeInfo( settings );
329             settings.setRuntimeInfo( rtInfo );
330         }
331 
332         return settings;
333     }
334 
335     public void setSettingsFile( File settingsFile )
336     {
337         if ( !settingsFile.exists() )
338         {
339             throw new BuildException( "settingsFile does not exist: " + settingsFile.getAbsolutePath() );
340         }
341 
342         userSettingsFile = settingsFile;
343         settings = null;
344     }
345 
346     /**
347      * @see org.apache.maven.settings.DefaultMavenSettingsBuilder#readSettings
348      */
349     private Settings readSettings( File settingsFile )
350         throws IOException, XmlPullParserException
351     {
352         Settings settings = null;
353         Reader reader = null;
354         try
355         {
356             reader = ReaderFactory.newXmlReader( settingsFile );
357             StringWriter sWriter = new StringWriter();
358 
359             IOUtil.copy( reader, sWriter );
360 
361             String rawInput = sWriter.toString();
362 
363             try
364             {
365                 RegexBasedInterpolator interpolator = new RegexBasedInterpolator();
366                 interpolator.addValueSource( new EnvarBasedValueSource() );
367 
368                 rawInput = interpolator.interpolate( rawInput, "settings" );
369             }
370             catch ( Exception e )
371             {
372                 log( "Failed to initialize environment variable resolver. Skipping environment substitution in "
373                      + "settings." );
374             }
375 
376             StringReader sReader = new StringReader( rawInput );
377 
378             SettingsXpp3Reader modelReader = new SettingsXpp3Reader();
379 
380             settings = modelReader.read( sReader );
381 
382             RuntimeInfo rtInfo = new RuntimeInfo( settings );
383 
384             rtInfo.setFile( settingsFile );
385 
386             settings.setRuntimeInfo( rtInfo );
387         }
388         finally
389         {
390             IOUtil.close( reader );
391         }
392         return settings;
393     }
394 
395     protected RemoteRepository createAntRemoteRepository( org.apache.maven.model.Repository pomRepository )
396     {
397         RemoteRepository r = createAntRemoteRepositoryBase( pomRepository );
398 
399         if ( pomRepository.getSnapshots() != null )
400         {
401             r.addSnapshots( convertRepositoryPolicy( pomRepository.getSnapshots() ) );
402         }
403         if ( pomRepository.getReleases() != null )
404         {
405             r.addReleases( convertRepositoryPolicy( pomRepository.getReleases() ) );
406         }
407 
408         return r;
409     }
410 
411     protected RemoteRepository createAntRemoteRepositoryBase( org.apache.maven.model.RepositoryBase pomRepository )
412     {
413         RemoteRepository r = new RemoteRepository();
414         r.setId( pomRepository.getId() );
415         r.setUrl( pomRepository.getUrl() );
416         r.setLayout( pomRepository.getLayout() );
417 
418         return r;
419     }
420 
421     protected void updateRepositoryWithSettings( RemoteRepository repository )
422     {
423         // TODO: actually, we need to not funnel this through the ant repository - we should pump settings into wagon
424         // manager at the start like m2 does, and then match up by repository id
425         // As is, this could potentially cause a problem with 2 remote repositories with different authentication info
426 
427         Mirror mirror = getMirror( getSettings().getMirrors(), repository );
428         if ( mirror != null )
429         {
430             repository.setUrl( mirror.getUrl() );
431             repository.setId( mirror.getId() );
432         }
433 
434         if ( repository.getAuthentication() == null )
435         {
436             Server server = getSettings().getServer( repository.getId() );
437             if ( server != null )
438             {
439                 repository.addAuthentication( new Authentication( server ) );
440             }
441         }
442 
443         if ( repository.getProxy() == null )
444         {
445             org.apache.maven.settings.Proxy proxy = getSettings().getActiveProxy();
446             if ( proxy != null )
447             {
448                 repository.addProxy( new Proxy( proxy ) );
449             }
450         }
451     }
452 
453     protected Object lookup( String role )
454     {
455         try
456         {
457             return getContainer().lookup( role );
458         }
459         catch ( ComponentLookupException e )
460         {
461             throw new BuildException( "Unable to find component: " + role, e );
462         }
463     }
464 
465     protected Object lookup( String role,
466                              String roleHint )
467     {
468         try
469         {
470             return getContainer().lookup( role, roleHint );
471         }
472         catch ( ComponentLookupException e )
473         {
474             throw new BuildException( "Unable to find component: " + role + "[" + roleHint + "]", e );
475         }
476     }
477 
478     protected synchronized PlexusContainer getContainer()
479     {
480         if ( container == null )
481         {
482             container = (PlexusContainer) getProject().getReference( PlexusContainer.class.getName() );
483 
484             if ( container == null )
485             {
486                 try
487                 {
488                     ClassWorld classWorld = new ClassWorld();
489 
490                     classWorld.newRealm( "plexus.core", getClass().getClassLoader() );
491 
492                     Embedder embedder = new Embedder();
493 
494                     embedder.start( classWorld );
495 
496                     container = embedder.getContainer();
497                 }
498                 catch ( PlexusContainerException e )
499                 {
500                     throw new BuildException( "Unable to start embedder", e );
501                 }
502                 catch ( DuplicateRealmException e )
503                 {
504                     throw new BuildException( "Unable to create embedder ClassRealm", e );
505                 }
506 
507                 getProject().addReference( PlexusContainer.class.getName(), container );
508             }
509         }
510 
511         return container;
512     }
513 
514     /**
515      * Tries to initialize the pom.  If no pom has been configured, returns null.
516      *
517      * @param localArtifactRepository
518      * @return An initialized pom or null.
519      */
520     public Pom initializePom( ArtifactRepository localArtifactRepository )
521     {
522 
523         Pom pom = getPom();
524         if ( pom != null )
525         {
526             MavenProjectBuilder projectBuilder = (MavenProjectBuilder) lookup( MavenProjectBuilder.ROLE );
527             pom.initialiseMavenProject( projectBuilder, localArtifactRepository );
528         }
529 
530         return pom;
531     }
532 
533     protected Pom createDummyPom( ArtifactRepository localRepository )
534     {
535         Pom pom = new Pom();
536 
537         MavenProject minimalProject = createMinimalProject( localRepository );
538         // we nulled out these fields to allow inheritance when creating poms, but the dummy
539         // needs to be a valid pom, so set them back to something that's OK to resolve
540         minimalProject.setGroupId( "org.apache.maven" );
541         minimalProject.setArtifactId( "super-pom" );
542         minimalProject.setVersion( "2.0" );
543         minimalProject.setPackaging( "pom" );
544         pom.setMavenProject( minimalProject );
545 
546         return pom;
547     }
548 
549     /**
550      * Create a minimal project when no POM is available.
551      *
552      * @param localRepository
553      * @return
554      */
555     protected MavenProject createMinimalProject( ArtifactRepository localRepository )
556     {
557         MavenProjectBuilder projectBuilder = (MavenProjectBuilder) lookup( MavenProjectBuilder.ROLE );
558         DefaultProjectBuilderConfiguration builderConfig = new DefaultProjectBuilderConfiguration( );
559         builderConfig.setLocalRepository( localRepository );
560         builderConfig.setGlobalProfileManager( getProfileManager() );
561 
562         try
563         {
564             MavenProject mavenProject = projectBuilder.buildStandaloneSuperProject(builderConfig);
565             // if we don't null out these fields then the pom that will be created is at the super-pom's
566             // GAV coordinates and we will not be able to inherit partial GAV coordinates from a parent GAV.
567             mavenProject.setGroupId(null);
568             mavenProject.setArtifactId(null);
569             mavenProject.setVersion(null);
570             return mavenProject;
571         }
572         catch ( ProjectBuildingException e )
573         {
574             throw new BuildException( "Unable to create dummy Pom", e );
575         }
576 
577     }
578 
579     protected Artifact createDummyArtifact()
580     {
581         ArtifactFactory factory = (ArtifactFactory) lookup( ArtifactFactory.ROLE );
582         // TODO: maybe not strictly correct, while we should enforce that packaging has a type handler of the same id, we don't
583         return factory.createBuildArtifact( "unspecified", "unspecified", "0.0", "jar" );
584     }
585 
586     public String[] getSupportedProtocols()
587     {
588         try
589         {
590             Map<String,Wagon> wagonMap = getContainer().lookupMap( Wagon.ROLE );
591             List<String> protocols = new ArrayList<String>();
592             for ( Map.Entry<String,Wagon> entry : wagonMap.entrySet() )
593             {
594                 protocols.add( entry.getKey() );
595             }
596             return (String[]) protocols.toArray( new String[protocols.size()] );
597         }
598         catch ( ComponentLookupException e )
599         {
600             throw new BuildException( "Unable to lookup Wagon providers", e );
601         }
602     }
603 
604     public String getSupportedProtocolsAsString()
605     {
606         return StringUtils.join( getSupportedProtocols(), ", " );
607     }
608 
609     public void diagnoseError( Throwable error )
610     {
611         try
612         {
613             ErrorDiagnostics diagnostics = (ErrorDiagnostics) container.lookup( ErrorDiagnostics.ROLE );
614 
615             StringBuffer message = new StringBuffer();
616 
617             message.append( "An error has occurred while processing the Maven artifact tasks.\n" );
618             message.append( " Diagnosis:\n\n" );
619 
620             message.append( diagnostics.diagnose( error ) );
621 
622             message.append( "\n\n" );
623 
624             log( message.toString(), Project.MSG_INFO );
625         }
626         catch ( ComponentLookupException e )
627         {
628             log( "Failed to retrieve error diagnoser.", Project.MSG_DEBUG );
629         }
630     }
631 
632     public void addPom( Pom pom )
633     {
634         this.pom = pom;
635     }
636 
637     /**
638      * Try to get the POM from the nested pom element or a pomRefId
639      *
640      * @return The pom object
641      */
642     public Pom getPom()
643     {
644         Pom thePom = this.pom;
645 
646         if ( thePom != null && getPomRefId() != null )
647         {
648             throw new BuildException( "You cannot specify both a nested \"pom\" element and a \"pomrefid\" attribute" );
649         }
650 
651         if ( getPomRefId() != null )
652         {
653             Object pomRefObj = getProject().getReference( getPomRefId() );
654             if ( pomRefObj instanceof Pom )
655             {
656                 thePom = (Pom) pomRefObj;
657             }
658             else
659             {
660                 throw new BuildException( "Reference '" + pomRefId + "' was not found." );
661             }
662         }
663 
664         return thePom;
665     }
666 
667     public String getPomRefId()
668     {
669         return pomRefId;
670     }
671 
672     /**
673      * Try to get all the poms with id's which have been added to the ANT project
674      * @return
675      */
676     public List/*<Pom>*/ getAntReactorPoms()
677     {
678         List result = new ArrayList();
679         Iterator i = getProject().getReferences().values().iterator();
680         while ( i.hasNext() )
681         {
682             Object ref = i.next();
683             if ( ref instanceof Pom )
684             {
685                 result.add( (Pom)ref );
686             }
687         }
688         return result;
689     }
690 
691     public void setPomRefId( String pomRefId )
692     {
693         this.pomRefId = pomRefId;
694     }
695 
696     public LocalRepository getLocalRepository()
697     {
698         if ( localRepository == null )
699         {
700             localRepository = getDefaultLocalRepository();
701         }
702         return localRepository;
703     }
704 
705     protected ProfileManager getProfileManager()
706     {
707         if ( profileManager == null )
708         {
709             profileManager = new DefaultProfileManager( getContainer(), getSettings(), System.getProperties() );
710         }
711         return profileManager;
712     }
713 
714     public void addLocalRepository( LocalRepository localRepository )
715     {
716         this.localRepository = localRepository;
717     }
718 
719     public void setProfiles( String profiles )
720     {
721         if ( profiles != null )
722         {
723             // TODO: not sure this is the best way to do this...
724             log( "Profiles not yet supported, ignoring profiles '" + profiles + "'", Project.MSG_WARN );
725 //            System.setProperty( ProfileActivationUtils.ACTIVE_PROFILE_IDS, profiles );
726         }
727     }
728 
729     private static RepositoryPolicy convertRepositoryPolicy( org.apache.maven.model.RepositoryPolicy pomRepoPolicy )
730     {
731         RepositoryPolicy policy = new RepositoryPolicy();
732         policy.setEnabled( pomRepoPolicy.isEnabled() );
733         policy.setUpdatePolicy( pomRepoPolicy.getUpdatePolicy() );
734         return policy;
735     }
736 
737     /** @noinspection RefusedBequest */
738     public void execute()
739     {
740         // Display the version if the log level is verbose
741         showVersion();
742 
743         ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
744         try
745         {
746             if ( plexusClassLoader != null )
747             {
748                 Thread.currentThread().setContextClassLoader( plexusClassLoader );
749             }
750             initSettings();
751             doExecute();
752         }
753         catch ( BuildException e )
754         {
755             diagnoseError( e );
756 
757             throw e;
758         }
759         finally
760         {
761             plexusClassLoader = Thread.currentThread().getContextClassLoader();
762             Thread.currentThread().setContextClassLoader( originalClassLoader );
763         }
764     }
765 
766     /**
767      * The main entry point for the task.
768      */
769     protected abstract void doExecute();
770 
771     /**
772      * This method finds a matching mirror for the selected repository. If there is an exact match,
773      * this will be used. If there is no exact match, then the list of mirrors is examined to see if
774      * a pattern applies.
775      *
776      * @param mirrors The available mirrors.
777      * @param repository See if there is a mirror for this repository.
778      * @return the selected mirror or null if none is found.
779      */
780     private Mirror getMirror( List<Mirror> mirrors, RemoteRepository repository )
781     {
782         String repositoryId = repository.getId();
783 
784         if ( repositoryId != null )
785         {
786             for ( Mirror mirror : mirrors )
787             {
788                 if ( repositoryId.equals( mirror.getMirrorOf() ) )
789                 {
790                     return mirror;
791                 }
792             }
793 
794             for ( Mirror mirror : mirrors )
795             {
796                 if ( matchPattern( repository, mirror.getMirrorOf() ) )
797                 {
798                     return mirror;
799                 }
800             }
801         }
802 
803         return null;
804     }
805 
806     /**
807      * This method checks if the pattern matches the originalRepository. Valid patterns: * =
808      * everything external:* = everything not on the localhost and not file based. repo,repo1 = repo
809      * or repo1 *,!repo1 = everything except repo1
810      *
811      * @param originalRepository to compare for a match.
812      * @param pattern used for match. Currently only '*' is supported.
813      * @return true if the repository is a match to this pattern.
814      */
815     boolean matchPattern( RemoteRepository originalRepository, String pattern )
816     {
817         boolean result = false;
818         String originalId = originalRepository.getId();
819 
820         // simple checks first to short circuit processing below.
821         if ( WILDCARD.equals( pattern ) || pattern.equals( originalId ) )
822         {
823             result = true;
824         }
825         else
826         {
827             // process the list
828             String[] repos = pattern.split( "," );
829 
830             for ( int i = 0; i < repos.length; i++ )
831             {
832                 String repo = repos[i];
833 
834                 // see if this is a negative match
835                 if ( repo.length() > 1 && repo.startsWith( "!" ) )
836                 {
837                     if ( originalId.equals( repo.substring( 1 ) ) )
838                     {
839                         // explicitly exclude. Set result and stop processing.
840                         result = false;
841                         break;
842                     }
843                 }
844                 // check for exact match
845                 else if ( originalId.equals( repo ) )
846                 {
847                     result = true;
848                     break;
849                 }
850                 // check for external:*
851                 else if ( EXTERNAL_WILDCARD.equals( repo ) && isExternalRepo( originalRepository ) )
852                 {
853                     result = true;
854                     // don't stop processing in case a future segment explicitly excludes this repo
855                 }
856                 else if ( WILDCARD.equals( repo ) )
857                 {
858                     result = true;
859                     // don't stop processing in case a future segment explicitly excludes this repo
860                 }
861             }
862         }
863         return result;
864     }
865 
866     /**
867      * Checks the URL to see if this repository refers to an external repository
868      *
869      * @param originalRepository
870      * @return true if external.
871      */
872     boolean isExternalRepo( RemoteRepository originalRepository )
873     {
874         try
875         {
876             URL url = new URL( originalRepository.getUrl() );
877             return !( url.getHost().equals( "localhost" ) || url.getHost().equals( "127.0.0.1" ) || url.getProtocol().equals( "file" ) );
878         }
879         catch ( MalformedURLException e )
880         {
881             // bad url just skip it here. It should have been validated already, but the wagon lookup will deal with it
882             return false;
883         }
884     }
885 
886     /**
887      * Log the current version of the ant-tasks to the verbose output.
888      */
889     protected void showVersion()
890     {
891 
892         Properties properties = new Properties();
893         final String antTasksPropertiesPath = "META-INF/maven/org.apache.maven/maven-ant-tasks/pom.properties";
894         InputStream resourceAsStream = AbstractArtifactTask.class.getClassLoader().getResourceAsStream( antTasksPropertiesPath );
895 
896         try
897         {
898             if ( resourceAsStream != null )
899             {
900                 properties.load( resourceAsStream );
901             }
902 
903             String version = properties.getProperty( "version", "unknown" );
904             String builtOn = properties.getProperty( "builtOn" );
905             if ( builtOn != null )
906             {
907                 log( "Maven Ant Tasks version: " + version + " built on " + builtOn, Project.MSG_VERBOSE );
908             }
909             else
910             {
911                 log( "Maven Ant Tasks version: " + version, Project.MSG_VERBOSE );
912             }
913         }
914         catch ( IOException e )
915         {
916             log( "Unable to determine version from Maven Ant Tasks JAR file: " + e.getMessage(), Project.MSG_WARN );
917         }
918     }
919 
920 }