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 createArtifactX( groupId, artifactId, version, scope, type );
80      }
81  
82      // DefaultProjectBuilder
83      public Artifact createProjectArtifact( String groupId, String artifactId, String metaVersionId )
84      {
85          return createProjectArtifactX( 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             createDependencyArtifactX( 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<>();
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 createExtensionArtifactX( groupId, artifactId, versionRange );
144     }
145 
146     // DefaultProjectBuilder
147     public Artifact createParentArtifact( String groupId, String artifactId, String version )
148     {
149         return createParentArtifactX( 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 createPluginArtifactX( 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 createArtifactX( String groupId, String artifactId, String version, String scope, String type )
475     {
476         return createArtifactX( groupId, artifactId, version, scope, type, null, null );
477     }
478 
479     private Artifact createDependencyArtifactX( String groupId, String artifactId, VersionRange versionRange,
480                                                String type, String classifier, String scope, boolean optional )
481     {
482         return createArtifactX( groupId, artifactId, versionRange, type, classifier, scope, null, optional );
483     }
484 
485     private Artifact createProjectArtifactX( String groupId, String artifactId, String version )
486     {
487         return createProjectArtifactX( groupId, artifactId, version, null );
488     }
489 
490     private Artifact createParentArtifactX( String groupId, String artifactId, String version )
491     {
492         return createProjectArtifactX( groupId, artifactId, version );
493     }
494 
495     private Artifact createPluginArtifactX( String groupId, String artifactId, VersionRange versionRange )
496     {
497         return createArtifactX( groupId, artifactId, versionRange, "maven-plugin", null, Artifact.SCOPE_RUNTIME, null );
498     }
499 
500     private Artifact createProjectArtifactX( String groupId, String artifactId, String version, String scope )
501     {
502         return createArtifactX( groupId, artifactId, version, scope, "pom" );
503     }
504 
505     private Artifact createExtensionArtifactX( String groupId, String artifactId, VersionRange versionRange )
506     {
507         return createArtifactX( groupId, artifactId, versionRange, "jar", null, Artifact.SCOPE_RUNTIME, null );
508     }
509 
510     private Artifact createArtifactX( 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 createArtifactX( groupId, artifactId, versionRange, type, classifier, scope, inheritedScope );
519     }
520 
521     private Artifact createArtifactX( String groupId, String artifactId, VersionRange versionRange, String type,
522                                      String classifier, String scope, String inheritedScope )
523     {
524         return createArtifactX( groupId, artifactId, versionRange, type, classifier, scope, inheritedScope, false );
525     }
526 
527     @SuppressWarnings( "checkstyle:parameternumber" )
528     private Artifact createArtifactX( String groupId, String artifactId, VersionRange versionRange, String type,
529                                      String classifier, String scope, String inheritedScope, boolean optional )
530     {
531         String desiredScope = Artifact.SCOPE_RUNTIME;
532 
533         if ( inheritedScope == null )
534         {
535             desiredScope = scope;
536         }
537         else if ( Artifact.SCOPE_TEST.equals( scope ) || Artifact.SCOPE_PROVIDED.equals( scope ) )
538         {
539             return null;
540         }
541         else if ( Artifact.SCOPE_COMPILE.equals( scope ) && Artifact.SCOPE_COMPILE.equals( inheritedScope ) )
542         {
543             // added to retain compile artifactScope. Remove if you want compile inherited as runtime
544             desiredScope = Artifact.SCOPE_COMPILE;
545         }
546 
547         if ( Artifact.SCOPE_TEST.equals( inheritedScope ) )
548         {
549             desiredScope = Artifact.SCOPE_TEST;
550         }
551 
552         if ( Artifact.SCOPE_PROVIDED.equals( inheritedScope ) )
553         {
554             desiredScope = Artifact.SCOPE_PROVIDED;
555         }
556 
557         if ( Artifact.SCOPE_SYSTEM.equals( scope ) )
558         {
559             // system scopes come through unchanged...
560             desiredScope = Artifact.SCOPE_SYSTEM;
561         }
562 
563         ArtifactHandler handler = artifactHandlerManager.getArtifactHandler( type );
564 
565         return new DefaultArtifact( groupId, artifactId, versionRange, desiredScope, type, classifier, handler,
566                                     optional );
567     }
568     
569     //
570     // Code taken from LegacyRepositorySystem
571     //
572         
573     public ArtifactRepository createDefaultRemoteRepository( MavenExecutionRequest request )
574         throws Exception
575     {
576         return createRepository( RepositorySystem.DEFAULT_REMOTE_REPO_URL, RepositorySystem.DEFAULT_REMOTE_REPO_ID,
577                                  true, ArtifactRepositoryPolicy.UPDATE_POLICY_DAILY, false,
578                                  ArtifactRepositoryPolicy.UPDATE_POLICY_DAILY,
579                                  ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN );
580     }
581     
582     public ArtifactRepository createRepository( String url, String repositoryId, boolean releases,
583                                                  String releaseUpdates, boolean snapshots, String snapshotUpdates,
584                                                  String checksumPolicy ) throws Exception
585     {
586         ArtifactRepositoryPolicy snapshotsPolicy =
587             new ArtifactRepositoryPolicy( snapshots, snapshotUpdates, checksumPolicy );
588 
589         ArtifactRepositoryPolicy releasesPolicy =
590             new ArtifactRepositoryPolicy( releases, releaseUpdates, checksumPolicy );
591 
592         return createArtifactRepository( repositoryId, url, "default", snapshotsPolicy, releasesPolicy );
593     }
594         
595     public Set<String> getRepoIds( List<ArtifactRepository> repositories )
596     {
597         Set<String> repoIds = new HashSet<>();
598 
599         if ( repositories != null )
600         {
601             for ( ArtifactRepository repository : repositories )
602             {
603                 repoIds.add( repository.getId() );
604             }
605         }
606 
607         return repoIds;
608     }
609     
610     
611     public ArtifactRepository createLocalRepository( MavenExecutionRequest request, File localRepository )
612         throws Exception
613     {
614         return createRepository( "file://" + localRepository.toURI().getRawPath(),
615                                  RepositorySystem.DEFAULT_LOCAL_REPO_ID, true,
616                                  ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS, true,
617                                  ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS,
618                                  ArtifactRepositoryPolicy.CHECKSUM_POLICY_IGNORE );
619     }    
620     
621     private static final String WILDCARD = "*";
622 
623     private static final String EXTERNAL_WILDCARD = "external:*";
624 
625     public static Mirror getMirror( ArtifactRepository repository, List<Mirror> mirrors )
626     {
627         String repoId = repository.getId();
628 
629         if ( repoId != null && mirrors != null )
630         {
631             for ( Mirror mirror : mirrors )
632             {
633                 if ( repoId.equals( mirror.getMirrorOf() ) && matchesLayout( repository, mirror ) )
634                 {
635                     return mirror;
636                 }
637             }
638 
639             for ( Mirror mirror : mirrors )
640             {
641                 if ( matchPattern( repository, mirror.getMirrorOf() ) && matchesLayout( repository, mirror ) )
642                 {
643                     return mirror;
644                 }
645             }
646         }
647 
648         return null;
649     }
650 
651     /**
652      * This method checks if the pattern matches the originalRepository. Valid patterns: * = everything external:* =
653      * everything not on the localhost and not file based. repo,repo1 = repo or repo1 *,!repo1 = everything except repo1
654      *
655      * @param originalRepository to compare for a match.
656      * @param pattern used for match. Currently only '*' is supported.
657      * @return true if the repository is a match to this pattern.
658      */
659     static boolean matchPattern( ArtifactRepository originalRepository, String pattern )
660     {
661         boolean result = false;
662         String originalId = originalRepository.getId();
663 
664         // simple checks first to short circuit processing below.
665         if ( WILDCARD.equals( pattern ) || pattern.equals( originalId ) )
666         {
667             result = true;
668         }
669         else
670         {
671             // process the list
672             String[] repos = pattern.split( "," );
673             for ( String repo : repos )
674             {
675                 // see if this is a negative match
676                 if ( repo.length() > 1 && repo.startsWith( "!" ) )
677                 {
678                     if ( repo.substring( 1 ).equals( originalId ) )
679                     {
680                         // explicitly exclude. Set result and stop processing.
681                         result = false;
682                         break;
683                     }
684                 }
685                 // check for exact match
686                 else if ( repo.equals( originalId ) )
687                 {
688                     result = true;
689                     break;
690                 }
691                 // check for external:*
692                 else if ( EXTERNAL_WILDCARD.equals( repo ) && isExternalRepo( originalRepository ) )
693                 {
694                     result = true;
695                     // don't stop processing in case a future segment explicitly excludes this repo
696                 }
697                 else if ( WILDCARD.equals( repo ) )
698                 {
699                     result = true;
700                     // don't stop processing in case a future segment explicitly excludes this repo
701                 }
702             }
703         }
704         return result;
705     }
706 
707     /**
708      * Checks the URL to see if this repository refers to an external repository
709      *
710      * @param originalRepository
711      * @return true if external.
712      */
713     static boolean isExternalRepo( ArtifactRepository originalRepository )
714     {
715         try
716         {
717             URL url = new URL( originalRepository.getUrl() );
718             return !( url.getHost().equals( "localhost" ) || url.getHost().equals( "127.0.0.1" )
719                             || url.getProtocol().equals( "file" ) );
720         }
721         catch ( MalformedURLException e )
722         {
723             // bad url just skip it here. It should have been validated already, but the wagon lookup will deal with it
724             return false;
725         }
726     }
727 
728     static boolean matchesLayout( ArtifactRepository repository, Mirror mirror )
729     {
730         return matchesLayout( RepositoryUtils.getLayout( repository ), mirror.getMirrorOfLayouts() );
731     }
732 
733     /**
734      * Checks whether the layouts configured for a mirror match with the layout of the repository.
735      *
736      * @param repoLayout The layout of the repository, may be {@code null}.
737      * @param mirrorLayout The layouts supported by the mirror, may be {@code null}.
738      * @return {@code true} if the layouts associated with the mirror match the layout of the original repository,
739      *         {@code false} otherwise.
740      */
741     static boolean matchesLayout( String repoLayout, String mirrorLayout )
742     {
743         boolean result = false;
744 
745         // simple checks first to short circuit processing below.
746         if ( StringUtils.isEmpty( mirrorLayout ) || WILDCARD.equals( mirrorLayout ) )
747         {
748             result = true;
749         }
750         else if ( mirrorLayout.equals( repoLayout ) )
751         {
752             result = true;
753         }
754         else
755         {
756             // process the list
757             String[] layouts = mirrorLayout.split( "," );
758             for ( String layout : layouts )
759             {
760                 // see if this is a negative match
761                 if ( layout.length() > 1 && layout.startsWith( "!" ) )
762                 {
763                     if ( layout.substring( 1 ).equals( repoLayout ) )
764                     {
765                         // explicitly exclude. Set result and stop processing.
766                         result = false;
767                         break;
768                     }
769                 }
770                 // check for exact match
771                 else if ( layout.equals( repoLayout ) )
772                 {
773                     result = true;
774                     break;
775                 }
776                 else if ( WILDCARD.equals( layout ) )
777                 {
778                     result = true;
779                     // don't stop processing in case a future segment explicitly excludes this repo
780                 }
781             }
782         }
783 
784         return result;
785     }    
786 }