1 package org.apache.maven.repository;
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.net.MalformedURLException;
23 import java.net.URL;
24 import java.util.List;
25
26 import org.apache.maven.artifact.repository.ArtifactRepository;
27 import org.apache.maven.settings.Mirror;
28 import org.codehaus.plexus.component.annotations.Component;
29 import org.codehaus.plexus.util.StringUtils;
30
31 @Component( role = MirrorSelector.class )
32 public class DefaultMirrorSelector
33 implements MirrorSelector
34 {
35
36 private static final String WILDCARD = "*";
37
38 private static final String EXTERNAL_WILDCARD = "external:*";
39
40 public Mirror getMirror( ArtifactRepository repository, List<Mirror> mirrors )
41 {
42 String repoId = repository.getId();
43
44 if ( repoId != null && mirrors != null )
45 {
46 for ( Mirror mirror : mirrors )
47 {
48 if ( repoId.equals( mirror.getMirrorOf() ) && matchesLayout( repository, mirror ) )
49 {
50 return mirror;
51 }
52 }
53
54 for ( Mirror mirror : mirrors )
55 {
56 if ( matchPattern( repository, mirror.getMirrorOf() ) && matchesLayout( repository, mirror ) )
57 {
58 return mirror;
59 }
60 }
61 }
62
63 return null;
64 }
65
66 /**
67 * This method checks if the pattern matches the originalRepository. Valid patterns: * =
68 * everything external:* = everything not on the localhost and not file based. repo,repo1 = repo
69 * or repo1 *,!repo1 = everything except repo1
70 *
71 * @param originalRepository to compare for a match.
72 * @param pattern used for match. Currently only '*' is supported.
73 * @return true if the repository is a match to this pattern.
74 */
75 static boolean matchPattern( ArtifactRepository originalRepository, String pattern )
76 {
77 boolean result = false;
78 String originalId = originalRepository.getId();
79
80 // simple checks first to short circuit processing below.
81 if ( WILDCARD.equals( pattern ) || pattern.equals( originalId ) )
82 {
83 result = true;
84 }
85 else
86 {
87 // process the list
88 String[] repos = pattern.split( "," );
89 for ( String repo : repos )
90 {
91 // see if this is a negative match
92 if ( repo.length() > 1 && repo.startsWith( "!" ) )
93 {
94 if ( repo.substring( 1 ).equals( originalId ) )
95 {
96 // explicitly exclude. Set result and stop processing.
97 result = false;
98 break;
99 }
100 }
101 // check for exact match
102 else if ( repo.equals( originalId ) )
103 {
104 result = true;
105 break;
106 }
107 // check for external:*
108 else if ( EXTERNAL_WILDCARD.equals( repo ) && isExternalRepo( originalRepository ) )
109 {
110 result = true;
111 // don't stop processing in case a future segment explicitly excludes this repo
112 }
113 else if ( WILDCARD.equals( repo ) )
114 {
115 result = true;
116 // don't stop processing in case a future segment explicitly excludes this repo
117 }
118 }
119 }
120 return result;
121 }
122
123 /**
124 * Checks the URL to see if this repository refers to an external repository
125 *
126 * @param originalRepository
127 * @return true if external.
128 */
129 static boolean isExternalRepo( ArtifactRepository originalRepository )
130 {
131 try
132 {
133 URL url = new URL( originalRepository.getUrl() );
134 return !( url.getHost().equals( "localhost" ) || url.getHost().equals( "127.0.0.1" )
135 || url.getProtocol().equals( "file" ) );
136 }
137 catch ( MalformedURLException e )
138 {
139 // bad url just skip it here. It should have been validated already, but the wagon lookup will deal with it
140 return false;
141 }
142 }
143
144 static boolean matchesLayout( ArtifactRepository repository, Mirror mirror )
145 {
146 return matchesLayout( repository.getLayout().getId(), mirror.getMirrorOfLayouts() );
147 }
148
149 /**
150 * Checks whether the layouts configured for a mirror match with the layout of the repository.
151 *
152 * @param repoLayout The layout of the repository, may be {@code null}.
153 * @param mirrorLayout The layouts supported by the mirror, may be {@code null}.
154 * @return {@code true} if the layouts associated with the mirror match the layout of the original repository,
155 * {@code false} otherwise.
156 */
157 static boolean matchesLayout( String repoLayout, String mirrorLayout )
158 {
159 boolean result = false;
160
161 // simple checks first to short circuit processing below.
162 if ( StringUtils.isEmpty( mirrorLayout ) || WILDCARD.equals( mirrorLayout ) )
163 {
164 result = true;
165 }
166 else if ( mirrorLayout.equals( repoLayout ) )
167 {
168 result = true;
169 }
170 else
171 {
172 // process the list
173 String[] layouts = mirrorLayout.split( "," );
174 for ( String layout : layouts )
175 {
176 // see if this is a negative match
177 if ( layout.length() > 1 && layout.startsWith( "!" ) )
178 {
179 if ( layout.substring( 1 ).equals( repoLayout ) )
180 {
181 // explicitly exclude. Set result and stop processing.
182 result = false;
183 break;
184 }
185 }
186 // check for exact match
187 else if ( layout.equals( repoLayout ) )
188 {
189 result = true;
190 break;
191 }
192 else if ( WILDCARD.equals( layout ) )
193 {
194 result = true;
195 // don't stop processing in case a future segment explicitly excludes this repo
196 }
197 }
198 }
199
200 return result;
201 }
202
203 }