View Javadoc
1   package org.apache.maven.bridge;
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.net.MalformedURLException;
24  import java.net.URL;
25  import java.util.ArrayList;
26  import java.util.Collection;
27  import java.util.Collections;
28  import java.util.HashSet;
29  import java.util.LinkedHashMap;
30  import java.util.List;
31  import java.util.Map;
32  import java.util.Set;
33  
34  import javax.inject.Inject;
35  import javax.inject.Named;
36  import javax.inject.Singleton;
37  
38  import org.apache.maven.RepositoryUtils;
39  import org.apache.maven.artifact.Artifact;
40  import org.apache.maven.artifact.DefaultArtifact;
41  import org.apache.maven.artifact.InvalidRepositoryException;
42  import org.apache.maven.artifact.handler.ArtifactHandler;
43  import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
44  import org.apache.maven.artifact.repository.ArtifactRepository;
45  import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
46  import org.apache.maven.artifact.repository.Authentication;
47  import org.apache.maven.artifact.repository.MavenArtifactRepository;
48  import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
49  import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout2;
50  import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
51  import org.apache.maven.artifact.resolver.filter.ExclusionArtifactFilter;
52  import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
53  import org.apache.maven.artifact.versioning.VersionRange;
54  import org.apache.maven.execution.MavenExecutionRequest;
55  import org.apache.maven.model.Dependency;
56  import org.apache.maven.model.Plugin;
57  import org.apache.maven.repository.Proxy;
58  import org.apache.maven.repository.RepositorySystem;
59  import org.apache.maven.settings.Mirror;
60  import org.codehaus.plexus.util.StringUtils;
61  import org.eclipse.aether.RepositorySystemSession;
62  import org.eclipse.aether.repository.AuthenticationContext;
63  import org.eclipse.aether.repository.AuthenticationSelector;
64  import org.eclipse.aether.repository.ProxySelector;
65  import org.eclipse.aether.repository.RemoteRepository;
66  
67  /**
68   * @author Jason van Zyl
69   */
70  @Named( "default" )
71  @Singleton
72  public class MavenRepositorySystem
73  {
74      private final ArtifactHandlerManager artifactHandlerManager;
75  
76      private final Map<String, ArtifactRepositoryLayout> layouts;
77  
78      @Inject
79      public MavenRepositorySystem( ArtifactHandlerManager artifactHandlerManager,
80              Map<String, ArtifactRepositoryLayout> layouts )
81      {
82          this.artifactHandlerManager = artifactHandlerManager;
83          this.layouts = layouts;
84      }
85  
86      // DefaultProjectBuilder
87      public Artifact createArtifact( String groupId, String artifactId, String version, String scope, String type )
88      {
89          return createArtifactX( groupId, artifactId, version, scope, type );
90      }
91  
92      // DefaultProjectBuilder
93      public Artifact createProjectArtifact( String groupId, String artifactId, String metaVersionId )
94      {
95          return createProjectArtifactX( groupId, artifactId, metaVersionId );
96      }
97  
98      // DefaultProjectBuilder
99      public Artifact createDependencyArtifact( Dependency d )
100     {
101         if ( d.getVersion() == null )
102         {
103             return null;
104         }
105 
106         VersionRange versionRange;
107         try
108         {
109             versionRange = VersionRange.createFromVersionSpec( d.getVersion() );
110         }
111         catch ( InvalidVersionSpecificationException e )
112         {
113             return null;
114         }
115 
116         Artifact artifact =
117             createDependencyArtifactX( d.getGroupId(), d.getArtifactId(), versionRange, d.getType(),
118                                                       d.getClassifier(), d.getScope(), d.isOptional() );
119 
120         if ( Artifact.SCOPE_SYSTEM.equals( d.getScope() ) && d.getSystemPath() != null )
121         {
122             artifact.setFile( new File( d.getSystemPath() ) );
123         }
124 
125         if ( !d.getExclusions().isEmpty() )
126         {
127             artifact.setDependencyFilter( new ExclusionArtifactFilter( d.getExclusions() ) );
128         }
129 
130         return artifact;
131     }
132 
133     // DefaultProjectBuilder
134     public Artifact createExtensionArtifact( String groupId, String artifactId, String version )
135     {
136         VersionRange versionRange;
137         try
138         {
139             versionRange = VersionRange.createFromVersionSpec( version );
140         }
141         catch ( InvalidVersionSpecificationException e )
142         {
143             return null;
144         }
145 
146         return createExtensionArtifactX( groupId, artifactId, versionRange );
147     }
148 
149     // DefaultProjectBuilder
150     public Artifact createParentArtifact( String groupId, String artifactId, String version )
151     {
152         return createParentArtifactX( groupId, artifactId, version );
153     }
154 
155     // DefaultProjectBuilder
156     public Artifact createPluginArtifact( Plugin plugin )
157     {
158         VersionRange versionRange;
159         try
160         {
161             String version = plugin.getVersion();
162             if ( StringUtils.isEmpty( version ) )
163             {
164                 version = "RELEASE";
165             }
166             versionRange = VersionRange.createFromVersionSpec( version );
167         }
168         catch ( InvalidVersionSpecificationException e )
169         {
170             return null;
171         }
172 
173         return createPluginArtifactX( plugin.getGroupId(), plugin.getArtifactId(), versionRange );
174     }
175 
176     public void injectMirror( List<ArtifactRepository> repositories, List<Mirror> mirrors )
177     {
178         if ( repositories != null && mirrors != null )
179         {
180             for ( ArtifactRepository repository : repositories )
181             {
182                 Mirror mirror = getMirror( repository, mirrors );
183                 injectMirror( repository, mirror );
184             }
185         }
186     }
187 
188     private Mirror getMirror( RepositorySystemSession session, ArtifactRepository repository )
189     {
190         if ( session != null )
191         {
192             org.eclipse.aether.repository.MirrorSelector selector = session.getMirrorSelector();
193             if ( selector != null )
194             {
195                 RemoteRepository repo = selector.getMirror( RepositoryUtils.toRepo( repository ) );
196                 if ( repo != null )
197                 {
198                     Mirror mirror = new Mirror();
199                     mirror.setId( repo.getId() );
200                     mirror.setUrl( repo.getUrl() );
201                     mirror.setLayout( repo.getContentType() );
202                     mirror.setBlocked( repo.isBlocked() );
203                     return mirror;
204                 }
205             }
206         }
207         return null;
208     }
209 
210     public void injectMirror( RepositorySystemSession session, List<ArtifactRepository> repositories )
211     {
212         if ( repositories != null && session != null )
213         {
214             for ( ArtifactRepository repository : repositories )
215             {
216                 Mirror mirror = getMirror( session, repository );
217                 injectMirror( repository, mirror );
218             }
219         }
220     }
221 
222     private void injectMirror( ArtifactRepository repository, Mirror mirror )
223     {
224         if ( mirror != null )
225         {
226             ArtifactRepository original =
227                 createArtifactRepository( repository.getId(), repository.getUrl(), repository.getLayout(),
228                                           repository.getSnapshots(), repository.getReleases() );
229 
230             repository.setMirroredRepositories( Collections.singletonList( original ) );
231 
232             repository.setId( mirror.getId() );
233             repository.setUrl( mirror.getUrl() );
234 
235             if ( StringUtils.isNotEmpty( mirror.getLayout() ) )
236             {
237                 repository.setLayout( getLayout( mirror.getLayout() ) );
238             }
239 
240             repository.setBlocked( mirror.isBlocked() );
241         }
242     }
243 
244     private Authentication getAuthentication( RepositorySystemSession session, ArtifactRepository repository )
245     {
246         if ( session != null )
247         {
248             AuthenticationSelector selector = session.getAuthenticationSelector();
249             if ( selector != null )
250             {
251                 RemoteRepository repo = RepositoryUtils.toRepo( repository );
252                 org.eclipse.aether.repository.Authentication auth = selector.getAuthentication( repo );
253                 if ( auth != null )
254                 {
255                     repo = new RemoteRepository.Builder( repo ).setAuthentication( auth ).build();
256                     AuthenticationContext authCtx = AuthenticationContext.forRepository( session, repo );
257                     Authentication result =
258                         new Authentication( authCtx.get( AuthenticationContext.USERNAME ),
259                                             authCtx.get( AuthenticationContext.PASSWORD ) );
260                     result.setPrivateKey( authCtx.get( AuthenticationContext.PRIVATE_KEY_PATH ) );
261                     result.setPassphrase( authCtx.get( AuthenticationContext.PRIVATE_KEY_PASSPHRASE ) );
262                     authCtx.close();
263                     return result;
264                 }
265             }
266         }
267         return null;
268     }
269 
270     public void injectAuthentication( RepositorySystemSession session, List<ArtifactRepository> repositories )
271     {
272         if ( repositories != null && session != null )
273         {
274             for ( ArtifactRepository repository : repositories )
275             {
276                 repository.setAuthentication( getAuthentication( session, repository ) );
277             }
278         }
279     }
280 
281     private Proxy getProxy( RepositorySystemSession session, ArtifactRepository repository )
282     {
283         if ( session != null )
284         {
285             ProxySelector selector = session.getProxySelector();
286             if ( selector != null )
287             {
288                 RemoteRepository repo = RepositoryUtils.toRepo( repository );
289                 org.eclipse.aether.repository.Proxy proxy = selector.getProxy( repo );
290                 if ( proxy != null )
291                 {
292                     Proxy p = new Proxy();
293                     p.setHost( proxy.getHost() );
294                     p.setProtocol( proxy.getType() );
295                     p.setPort( proxy.getPort() );
296                     if ( proxy.getAuthentication() != null )
297                     {
298                         repo = new RemoteRepository.Builder( repo ).setProxy( proxy ).build();
299                         AuthenticationContext authCtx = AuthenticationContext.forProxy( session, repo );
300                         p.setUserName( authCtx.get( AuthenticationContext.USERNAME ) );
301                         p.setPassword( authCtx.get( AuthenticationContext.PASSWORD ) );
302                         p.setNtlmDomain( authCtx.get( AuthenticationContext.NTLM_DOMAIN ) );
303                         p.setNtlmHost( authCtx.get( AuthenticationContext.NTLM_WORKSTATION ) );
304                         authCtx.close();
305                     }
306                     return p;
307                 }
308             }
309         }
310         return null;
311     }
312 
313     public void injectProxy( RepositorySystemSession session, List<ArtifactRepository> repositories )
314     {
315         if ( repositories != null && session != null )
316         {
317             for ( ArtifactRepository repository : repositories )
318             {
319                 repository.setProxy( getProxy( session, repository ) );
320             }
321         }
322     }
323 
324     private ArtifactRepositoryLayout getLayout( String id )
325     {
326         return layouts.get( id );
327     }
328 
329 
330     //
331     // Taken from LegacyRepositorySystem
332     //
333 
334     public static org.apache.maven.model.Repository fromSettingsRepository( org.apache.maven.settings.Repository
335                                                                             settingsRepository )
336     {
337         org.apache.maven.model.Repository modelRepository = new org.apache.maven.model.Repository();
338         modelRepository.setId( settingsRepository.getId() );
339         modelRepository.setLayout( settingsRepository.getLayout() );
340         modelRepository.setName( settingsRepository.getName() );
341         modelRepository.setUrl( settingsRepository.getUrl() );
342         modelRepository.setReleases( fromSettingsRepositoryPolicy( settingsRepository.getReleases() ) );
343         modelRepository.setSnapshots( fromSettingsRepositoryPolicy( settingsRepository.getSnapshots() ) );
344         return modelRepository;
345     }
346 
347     public static org.apache.maven.model.RepositoryPolicy fromSettingsRepositoryPolicy(
348                                                  org.apache.maven.settings.RepositoryPolicy settingsRepositoryPolicy )
349     {
350         org.apache.maven.model.RepositoryPolicy modelRepositoryPolicy = new org.apache.maven.model.RepositoryPolicy();
351         if ( settingsRepositoryPolicy != null )
352         {
353             modelRepositoryPolicy.setEnabled( settingsRepositoryPolicy.isEnabled() );
354             modelRepositoryPolicy.setUpdatePolicy( settingsRepositoryPolicy.getUpdatePolicy() );
355             modelRepositoryPolicy.setChecksumPolicy( settingsRepositoryPolicy.getChecksumPolicy() );
356         }
357         return modelRepositoryPolicy;
358     }
359 
360     public static ArtifactRepository buildArtifactRepository( org.apache.maven.settings.Repository repo )
361         throws InvalidRepositoryException
362     {
363         return buildArtifactRepository( fromSettingsRepository( repo ) );
364     }
365 
366     public static ArtifactRepository buildArtifactRepository( org.apache.maven.model.Repository repo )
367         throws InvalidRepositoryException
368     {
369         if ( repo != null )
370         {
371             String id = repo.getId();
372 
373             if ( StringUtils.isEmpty( id ) )
374             {
375                 throw new InvalidRepositoryException( "Repository identifier missing", "" );
376             }
377 
378             String url = repo.getUrl();
379 
380             if ( StringUtils.isEmpty( url ) )
381             {
382                 throw new InvalidRepositoryException( "URL missing for repository " + id, id );
383             }
384 
385             ArtifactRepositoryPolicy snapshots = buildArtifactRepositoryPolicy( repo.getSnapshots() );
386 
387             ArtifactRepositoryPolicy releases = buildArtifactRepositoryPolicy( repo.getReleases() );
388 
389             ArtifactRepositoryLayout layout = new DefaultRepositoryLayout();
390 
391             return createArtifactRepository( id, url, layout, snapshots, releases );
392         }
393         else
394         {
395             return null;
396         }
397     }
398 
399     public static ArtifactRepositoryPolicy buildArtifactRepositoryPolicy( org.apache.maven.model.RepositoryPolicy
400                                                                           policy )
401     {
402         boolean enabled = true;
403 
404         String updatePolicy = null;
405 
406         String checksumPolicy = null;
407 
408         if ( policy != null )
409         {
410             enabled = policy.isEnabled();
411 
412             if ( policy.getUpdatePolicy() != null )
413             {
414                 updatePolicy = policy.getUpdatePolicy();
415             }
416             if ( policy.getChecksumPolicy() != null )
417             {
418                 checksumPolicy = policy.getChecksumPolicy();
419             }
420         }
421 
422         return new ArtifactRepositoryPolicy( enabled, updatePolicy, checksumPolicy );
423     }
424 
425     public ArtifactRepository createArtifactRepository( String id, String url, String layoutId,
426                                                         ArtifactRepositoryPolicy snapshots,
427                                                         ArtifactRepositoryPolicy releases )
428         throws Exception
429     {
430         ArtifactRepositoryLayout layout = layouts.get( layoutId );
431 
432         checkLayout( id, layoutId, layout );
433 
434         return createArtifactRepository( id, url, layout, snapshots, releases );
435     }
436 
437     private void checkLayout( String repositoryId, String layoutId, ArtifactRepositoryLayout layout )
438         throws Exception
439     {
440         if ( layout == null )
441         {
442             throw new Exception( String.format( "Cannot find ArtifactRepositoryLayout instance for: %s %s", layoutId,
443                                                 repositoryId ) );
444         }
445     }
446 
447     public static ArtifactRepository createArtifactRepository( String id, String url,
448                                                         ArtifactRepositoryLayout repositoryLayout,
449                                                         ArtifactRepositoryPolicy snapshots,
450                                                         ArtifactRepositoryPolicy releases )
451     {
452         if ( snapshots == null )
453         {
454             snapshots = new ArtifactRepositoryPolicy();
455         }
456 
457         if ( releases == null )
458         {
459             releases = new ArtifactRepositoryPolicy();
460         }
461 
462         ArtifactRepository repository;
463         if ( repositoryLayout instanceof ArtifactRepositoryLayout2 )
464         {
465             repository =
466                 ( (ArtifactRepositoryLayout2) repositoryLayout ).newMavenArtifactRepository( id, url, snapshots,
467                                                                                              releases );
468         }
469         else
470         {
471             repository = new MavenArtifactRepository( id, url, repositoryLayout, snapshots, releases );
472         }
473 
474         return repository;
475     }
476 
477     // ArtifactFactory
478     private Artifact createArtifactX( String groupId, String artifactId, String version, String scope, String type )
479     {
480         return createArtifactX( groupId, artifactId, version, scope, type, null, null );
481     }
482 
483     private Artifact createDependencyArtifactX( String groupId, String artifactId, VersionRange versionRange,
484                                                String type, String classifier, String scope, boolean optional )
485     {
486         return createArtifactX( groupId, artifactId, versionRange, type, classifier, scope, null, optional );
487     }
488 
489     private Artifact createProjectArtifactX( String groupId, String artifactId, String version )
490     {
491         return createProjectArtifactX( groupId, artifactId, version, null );
492     }
493 
494     private Artifact createParentArtifactX( String groupId, String artifactId, String version )
495     {
496         return createProjectArtifactX( groupId, artifactId, version );
497     }
498 
499     private Artifact createPluginArtifactX( String groupId, String artifactId, VersionRange versionRange )
500     {
501         return createArtifactX( groupId, artifactId, versionRange, "maven-plugin", null, Artifact.SCOPE_RUNTIME, null );
502     }
503 
504     private Artifact createProjectArtifactX( String groupId, String artifactId, String version, String scope )
505     {
506         return createArtifactX( groupId, artifactId, version, scope, "pom" );
507     }
508 
509     private Artifact createExtensionArtifactX( String groupId, String artifactId, VersionRange versionRange )
510     {
511         return createArtifactX( groupId, artifactId, versionRange, "jar", null, Artifact.SCOPE_RUNTIME, null );
512     }
513 
514     private Artifact createArtifactX( String groupId, String artifactId, String version, String scope, String type,
515                                      String classifier, String inheritedScope )
516     {
517         VersionRange versionRange = null;
518         if ( version != null )
519         {
520             versionRange = VersionRange.createFromVersion( version );
521         }
522         return createArtifactX( groupId, artifactId, versionRange, type, classifier, scope, inheritedScope );
523     }
524 
525     private Artifact createArtifactX( String groupId, String artifactId, VersionRange versionRange, String type,
526                                      String classifier, String scope, String inheritedScope )
527     {
528         return createArtifactX( groupId, artifactId, versionRange, type, classifier, scope, inheritedScope, false );
529     }
530 
531     @SuppressWarnings( "checkstyle:parameternumber" )
532     private Artifact createArtifactX( String groupId, String artifactId, VersionRange versionRange, String type,
533                                      String classifier, String scope, String inheritedScope, boolean optional )
534     {
535         String desiredScope = Artifact.SCOPE_RUNTIME;
536 
537         if ( inheritedScope == null )
538         {
539             desiredScope = scope;
540         }
541         else if ( Artifact.SCOPE_TEST.equals( scope ) || Artifact.SCOPE_PROVIDED.equals( scope ) )
542         {
543             return null;
544         }
545         else if ( Artifact.SCOPE_COMPILE.equals( scope ) && Artifact.SCOPE_COMPILE.equals( inheritedScope ) )
546         {
547             // added to retain compile artifactScope. Remove if you want compile inherited as runtime
548             desiredScope = Artifact.SCOPE_COMPILE;
549         }
550 
551         if ( Artifact.SCOPE_TEST.equals( inheritedScope ) )
552         {
553             desiredScope = Artifact.SCOPE_TEST;
554         }
555 
556         if ( Artifact.SCOPE_PROVIDED.equals( inheritedScope ) )
557         {
558             desiredScope = Artifact.SCOPE_PROVIDED;
559         }
560 
561         if ( Artifact.SCOPE_SYSTEM.equals( scope ) )
562         {
563             // system scopes come through unchanged...
564             desiredScope = Artifact.SCOPE_SYSTEM;
565         }
566 
567         ArtifactHandler handler = artifactHandlerManager.getArtifactHandler( type );
568 
569         return new DefaultArtifact( groupId, artifactId, versionRange, desiredScope, type, classifier, handler,
570                                     optional );
571     }
572 
573     //
574     // Code taken from LegacyRepositorySystem
575     //
576 
577     public ArtifactRepository createDefaultRemoteRepository( MavenExecutionRequest request )
578         throws Exception
579     {
580         return createRepository( RepositorySystem.DEFAULT_REMOTE_REPO_URL, RepositorySystem.DEFAULT_REMOTE_REPO_ID,
581                                  true, ArtifactRepositoryPolicy.UPDATE_POLICY_DAILY, false,
582                                  ArtifactRepositoryPolicy.UPDATE_POLICY_DAILY,
583                                  ArtifactRepositoryPolicy.DEFAULT_CHECKSUM_POLICY );
584     }
585 
586     public ArtifactRepository createRepository( String url, String repositoryId, boolean releases,
587                                                  String releaseUpdates, boolean snapshots, String snapshotUpdates,
588                                                  String checksumPolicy ) throws Exception
589     {
590         ArtifactRepositoryPolicy snapshotsPolicy =
591             new ArtifactRepositoryPolicy( snapshots, snapshotUpdates, checksumPolicy );
592 
593         ArtifactRepositoryPolicy releasesPolicy =
594             new ArtifactRepositoryPolicy( releases, releaseUpdates, checksumPolicy );
595 
596         return createArtifactRepository( repositoryId, url, "default", snapshotsPolicy, releasesPolicy );
597     }
598 
599     public Set<String> getRepoIds( List<ArtifactRepository> repositories )
600     {
601         Set<String> repoIds = new HashSet<>();
602 
603         if ( repositories != null )
604         {
605             for ( ArtifactRepository repository : repositories )
606             {
607                 repoIds.add( repository.getId() );
608             }
609         }
610 
611         return repoIds;
612     }
613 
614     /**
615      * Source from org.apache.maven.repository.legacy.LegacyRepositorySystem#getEffectiveRepositories
616      *
617      * @param repositories a list of repositories
618      * @return corresponding effective repositories
619      * @since 3.6.1
620      */
621     public List<ArtifactRepository> getEffectiveRepositories( List<ArtifactRepository> repositories )
622     {
623         if ( repositories == null )
624         {
625             return null;
626         }
627 
628         Map<String, List<ArtifactRepository>> reposByKey = new LinkedHashMap<>();
629 
630         for ( ArtifactRepository repository : repositories )
631         {
632             String key = repository.getId();
633 
634             List<ArtifactRepository> aliasedRepos = reposByKey.computeIfAbsent( key, k -> new ArrayList<>() );
635 
636             aliasedRepos.add( repository );
637         }
638 
639         List<ArtifactRepository> effectiveRepositories = new ArrayList<>();
640 
641         for ( List<ArtifactRepository> aliasedRepos : reposByKey.values() )
642         {
643             List<ArtifactRepository> mirroredRepos = new ArrayList<>();
644 
645             List<ArtifactRepositoryPolicy> releasePolicies =
646                     new ArrayList<>( aliasedRepos.size() );
647 
648             for ( ArtifactRepository aliasedRepo : aliasedRepos )
649             {
650                 releasePolicies.add( aliasedRepo.getReleases() );
651                 mirroredRepos.addAll( aliasedRepo.getMirroredRepositories() );
652             }
653 
654             ArtifactRepositoryPolicy releasePolicy = getEffectivePolicy( releasePolicies );
655 
656             List<ArtifactRepositoryPolicy> snapshotPolicies =
657                     new ArrayList<>( aliasedRepos.size() );
658 
659             for ( ArtifactRepository aliasedRepo : aliasedRepos )
660             {
661                 snapshotPolicies.add( aliasedRepo.getSnapshots() );
662             }
663 
664             ArtifactRepositoryPolicy snapshotPolicy = getEffectivePolicy( snapshotPolicies );
665 
666             ArtifactRepository aliasedRepo = aliasedRepos.get( 0 );
667 
668             ArtifactRepository effectiveRepository =
669                     createArtifactRepository( aliasedRepo.getId(), aliasedRepo.getUrl(), aliasedRepo.getLayout(),
670                             snapshotPolicy, releasePolicy );
671 
672             effectiveRepository.setAuthentication( aliasedRepo.getAuthentication() );
673 
674             effectiveRepository.setProxy( aliasedRepo.getProxy() );
675 
676             effectiveRepository.setMirroredRepositories( mirroredRepos );
677 
678             effectiveRepository.setBlocked( aliasedRepo.isBlocked() );
679 
680             effectiveRepositories.add( effectiveRepository );
681         }
682 
683         return effectiveRepositories;
684     }
685 
686     private ArtifactRepositoryPolicy getEffectivePolicy( Collection<ArtifactRepositoryPolicy> policies )
687     {
688         ArtifactRepositoryPolicy effectivePolicy = null;
689 
690         for ( ArtifactRepositoryPolicy policy : policies )
691         {
692             if ( effectivePolicy == null )
693             {
694                 effectivePolicy = new ArtifactRepositoryPolicy( policy );
695             }
696             else
697             {
698                 effectivePolicy.merge( policy );
699             }
700         }
701 
702         return effectivePolicy;
703     }
704 
705     public ArtifactRepository createLocalRepository( MavenExecutionRequest request, File localRepository )
706         throws Exception
707     {
708         return createRepository( "file://" + localRepository.toURI().getRawPath(),
709                                  RepositorySystem.DEFAULT_LOCAL_REPO_ID, true,
710                                  ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS, true,
711                                  ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS,
712                                  ArtifactRepositoryPolicy.CHECKSUM_POLICY_IGNORE );
713     }
714 
715     private static final String WILDCARD = "*";
716 
717     private static final String EXTERNAL_WILDCARD = "external:*";
718 
719     private static final String EXTERNAL_HTTP_WILDCARD = "external:http:*";
720 
721     public static Mirror getMirror( ArtifactRepository repository, List<Mirror> mirrors )
722     {
723         String repoId = repository.getId();
724 
725         if ( repoId != null && mirrors != null )
726         {
727             for ( Mirror mirror : mirrors )
728             {
729                 if ( repoId.equals( mirror.getMirrorOf() ) && matchesLayout( repository, mirror ) )
730                 {
731                     return mirror;
732                 }
733             }
734 
735             for ( Mirror mirror : mirrors )
736             {
737                 if ( matchPattern( repository, mirror.getMirrorOf() ) && matchesLayout( repository, mirror ) )
738                 {
739                     return mirror;
740                 }
741             }
742         }
743 
744         return null;
745     }
746 
747     /**
748      * This method checks if the pattern matches the originalRepository. Valid patterns:
749      * <ul>
750      * <li>{@code *} = everything,</li>
751      * <li>{@code external:*} = everything not on the localhost and not file based,</li>
752      * <li>{@code external:http:*} = any repository not on the localhost using HTTP,</li>
753      * <li>{@code repo,repo1} = {@code repo} or {@code repo1},</li>
754      * <li>{@code *,!repo1} = everything except {@code repo1}.</li>
755      * </ul>
756      *
757      * @param originalRepository to compare for a match.
758      * @param pattern used for match.
759      * @return true if the repository is a match to this pattern.
760      */
761     static boolean matchPattern( ArtifactRepository originalRepository, String pattern )
762     {
763         boolean result = false;
764         String originalId = originalRepository.getId();
765 
766         // simple checks first to short circuit processing below.
767         if ( WILDCARD.equals( pattern ) || pattern.equals( originalId ) )
768         {
769             result = true;
770         }
771         else
772         {
773             // process the list
774             String[] repos = pattern.split( "," );
775             for ( String repo : repos )
776             {
777                 // see if this is a negative match
778                 if ( repo.length() > 1 && repo.startsWith( "!" ) )
779                 {
780                     if ( repo.substring( 1 ).equals( originalId ) )
781                     {
782                         // explicitly exclude. Set result and stop processing.
783                         result = false;
784                         break;
785                     }
786                 }
787                 // check for exact match
788                 else if ( repo.equals( originalId ) )
789                 {
790                     result = true;
791                     break;
792                 }
793                 // check for external:*
794                 else if ( EXTERNAL_WILDCARD.equals( repo ) && isExternalRepo( originalRepository ) )
795                 {
796                     result = true;
797                     // don't stop processing in case a future segment explicitly excludes this repo
798                 }
799                 // check for external:http:*
800                 else if ( EXTERNAL_HTTP_WILDCARD.equals( repo ) && isExternalHttpRepo( originalRepository ) )
801                 {
802                     result = true;
803                     // don't stop processing in case a future segment explicitly excludes this repo
804                 }
805                 else if ( WILDCARD.equals( repo ) )
806                 {
807                     result = true;
808                     // don't stop processing in case a future segment explicitly excludes this repo
809                 }
810             }
811         }
812         return result;
813     }
814 
815     /**
816      * Checks the URL to see if this repository refers to an external repository
817      *
818      * @param originalRepository
819      * @return true if external.
820      */
821     static boolean isExternalRepo( ArtifactRepository originalRepository )
822     {
823         try
824         {
825             URL url = new URL( originalRepository.getUrl() );
826             return !( isLocal( url.getHost() ) || url.getProtocol().equals( "file" ) );
827         }
828         catch ( MalformedURLException e )
829         {
830             // bad url just skip it here. It should have been validated already, but the wagon lookup will deal with it
831             return false;
832         }
833     }
834 
835     private static boolean isLocal( String host )
836     {
837         return "localhost".equals( host ) || "127.0.0.1".equals( host );
838     }
839 
840     /**
841      * Checks the URL to see if this repository refers to a non-localhost repository using HTTP.
842      *
843      * @param originalRepository
844      * @return true if external.
845      */
846     static boolean isExternalHttpRepo( ArtifactRepository originalRepository )
847     {
848         try
849         {
850             URL url = new URL( originalRepository.getUrl() );
851             return ( "http".equalsIgnoreCase( url.getProtocol() ) || "dav".equalsIgnoreCase( url.getProtocol() )
852                 || "dav:http".equalsIgnoreCase( url.getProtocol() )
853                 || "dav+http".equalsIgnoreCase( url.getProtocol() ) ) && !isLocal( url.getHost() );
854         }
855         catch ( MalformedURLException e )
856         {
857             // bad url just skip it here. It should have been validated already, but the wagon lookup will deal with it
858             return false;
859         }
860     }
861 
862     static boolean matchesLayout( ArtifactRepository repository, Mirror mirror )
863     {
864         return matchesLayout( RepositoryUtils.getLayout( repository ), mirror.getMirrorOfLayouts() );
865     }
866 
867     /**
868      * Checks whether the layouts configured for a mirror match with the layout of the repository.
869      *
870      * @param repoLayout The layout of the repository, may be {@code null}.
871      * @param mirrorLayout The layouts supported by the mirror, may be {@code null}.
872      * @return {@code true} if the layouts associated with the mirror match the layout of the original repository,
873      *         {@code false} otherwise.
874      */
875     static boolean matchesLayout( String repoLayout, String mirrorLayout )
876     {
877         boolean result = false;
878 
879         // simple checks first to short circuit processing below.
880         if ( StringUtils.isEmpty( mirrorLayout ) || WILDCARD.equals( mirrorLayout ) )
881         {
882             result = true;
883         }
884         else if ( mirrorLayout.equals( repoLayout ) )
885         {
886             result = true;
887         }
888         else
889         {
890             // process the list
891             String[] layouts = mirrorLayout.split( "," );
892             for ( String layout : layouts )
893             {
894                 // see if this is a negative match
895                 if ( layout.length() > 1 && layout.startsWith( "!" ) )
896                 {
897                     if ( layout.substring( 1 ).equals( repoLayout ) )
898                     {
899                         // explicitly exclude. Set result and stop processing.
900                         result = false;
901                         break;
902                     }
903                 }
904                 // check for exact match
905                 else if ( layout.equals( repoLayout ) )
906                 {
907                     result = true;
908                     break;
909                 }
910                 else if ( WILDCARD.equals( layout ) )
911                 {
912                     result = true;
913                     // don't stop processing in case a future segment explicitly excludes this repo
914                 }
915             }
916         }
917 
918         return result;
919     }
920 }