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