1 package org.apache.maven.archetype.source;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.util.List;
25 import java.util.Map;
26
27 import org.apache.maven.archetype.catalog.Archetype;
28 import org.apache.maven.archetype.catalog.ArchetypeCatalog;
29 import org.apache.maven.artifact.repository.ArtifactRepository;
30 import org.apache.maven.execution.MavenExecutionRequest;
31 import org.apache.maven.execution.MavenSession;
32 import org.apache.maven.plugin.LegacySupport;
33 import org.apache.maven.project.ProjectBuildingRequest;
34 import org.apache.maven.settings.Mirror;
35 import org.apache.maven.settings.Proxy;
36 import org.apache.maven.settings.Server;
37 import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest;
38 import org.apache.maven.settings.crypto.SettingsDecrypter;
39 import org.apache.maven.settings.crypto.SettingsDecryptionResult;
40 import org.apache.maven.wagon.UnsupportedProtocolException;
41 import org.apache.maven.wagon.Wagon;
42 import org.apache.maven.wagon.WagonException;
43 import org.apache.maven.wagon.authentication.AuthenticationInfo;
44 import org.apache.maven.wagon.proxy.ProxyInfo;
45 import org.apache.maven.wagon.repository.Repository;
46 import org.codehaus.plexus.component.annotations.Component;
47 import org.codehaus.plexus.component.annotations.Requirement;
48 import org.codehaus.plexus.util.ReaderFactory;
49 import org.codehaus.plexus.util.StringUtils;
50
51
52
53
54 @Component( role = ArchetypeDataSource.class, hint = "remote-catalog" )
55 public class RemoteCatalogArchetypeDataSource extends CatalogArchetypeDataSource implements ArchetypeDataSource
56 {
57 @Requirement
58 private Map<String, Wagon> wagons;
59
60 @Requirement
61 private LegacySupport legacySupport;
62
63 @Requirement
64 private SettingsDecrypter settingsDecrypter;
65
66
67
68
69
70
71
72
73
74
75 public static final String ARCHETYPE_REPOSITORY_ID = "archetype";
76
77 public static final String CENTRAL_REPOSITORY_ID = "central";
78
79 @Override
80 public ArchetypeCatalog getArchetypeCatalog( ProjectBuildingRequest buildingRequest )
81 throws ArchetypeDataSourceException
82 {
83
84
85 final String archetypeRepoId;
86 Mirror archetypeMirror = getMirror( ARCHETYPE_REPOSITORY_ID );
87 if ( archetypeMirror != null )
88 {
89 archetypeRepoId = archetypeMirror.getId();
90 }
91 else
92 {
93 archetypeRepoId = ARCHETYPE_REPOSITORY_ID;
94 }
95
96 final String centralRepoId;
97 Mirror centralMirror = getMirror( CENTRAL_REPOSITORY_ID );
98 if ( centralMirror != null )
99 {
100 centralRepoId = centralMirror.getId();
101 }
102 else
103 {
104 centralRepoId = CENTRAL_REPOSITORY_ID;
105 }
106
107 ArtifactRepository centralRepository = null;
108 ArtifactRepository archetypeRepository = null;
109 for ( ArtifactRepository remoteRepository : buildingRequest.getRemoteRepositories() )
110 {
111 if ( archetypeRepoId.equals( remoteRepository.getId() ) )
112 {
113 archetypeRepository = remoteRepository;
114 break;
115 }
116 else if ( centralRepoId.equals( remoteRepository.getId() ) )
117 {
118 centralRepository = remoteRepository;
119 }
120 }
121
122 if ( archetypeRepository == null )
123 {
124 archetypeRepository = centralRepository;
125 }
126
127 try
128 {
129 return downloadCatalog( archetypeRepository );
130 }
131 catch ( IOException e )
132 {
133 throw new ArchetypeDataSourceException( e );
134 }
135 catch ( WagonException e )
136 {
137 throw new ArchetypeDataSourceException( e );
138 }
139 }
140
141 @Override
142 public void updateCatalog( ProjectBuildingRequest buildingRequest, Archetype archetype )
143 throws ArchetypeDataSourceException
144 {
145 throw new ArchetypeDataSourceException( "Not supported yet." );
146 }
147
148 private ArchetypeCatalog downloadCatalog( ArtifactRepository repository )
149 throws WagonException, IOException, ArchetypeDataSourceException
150 {
151 getLogger().debug( "Searching for remote catalog: " + repository.getUrl() + "/" + ARCHETYPE_CATALOG_FILENAME );
152
153
154 Repository wagonRepository = new Repository( repository.getId(), repository.getUrl() );
155
156 AuthenticationInfo authInfo = getAuthenticationInfo( wagonRepository.getId() );
157 ProxyInfo proxyInfo = getProxy( wagonRepository.getProtocol() );
158
159 Wagon wagon = getWagon( wagonRepository );
160
161 File catalog = File.createTempFile( "archetype-catalog", ".xml" );
162 try
163 {
164 wagon.connect( wagonRepository, authInfo, proxyInfo );
165 wagon.get( ARCHETYPE_CATALOG_FILENAME, catalog );
166
167 return readCatalog( ReaderFactory.newXmlReader( catalog ) );
168 }
169 finally
170 {
171 disconnectWagon( wagon );
172 catalog.delete();
173 }
174 }
175
176 private void disconnectWagon( Wagon wagon )
177 {
178 try
179 {
180 wagon.disconnect();
181 }
182 catch ( Exception e )
183 {
184 getLogger().warn( "Problem disconnecting from wagon - ignoring: " + e.getMessage() );
185 }
186 }
187
188
189
190 private Wagon getWagon( Repository repository )
191 throws UnsupportedProtocolException
192 {
193 return getWagon( repository.getProtocol() );
194 }
195
196 private Wagon getWagon( String protocol )
197 throws UnsupportedProtocolException
198 {
199 if ( protocol == null )
200 {
201 throw new UnsupportedProtocolException( "Unspecified protocol" );
202 }
203
204 String hint = protocol.toLowerCase( java.util.Locale.ENGLISH );
205
206 Wagon wagon = wagons.get( hint );
207 if ( wagon == null )
208 {
209 throw new UnsupportedProtocolException( "Cannot find wagon which supports the requested protocol: "
210 + protocol );
211 }
212
213 return wagon;
214 }
215
216 private AuthenticationInfo getAuthenticationInfo( String id )
217 {
218 MavenSession session = legacySupport.getSession();
219
220 if ( session != null && id != null )
221 {
222 MavenExecutionRequest request = session.getRequest();
223
224 if ( request != null )
225 {
226 List<Server> servers = request.getServers();
227
228 if ( servers != null )
229 {
230 for ( Server server : servers )
231 {
232 if ( id.equalsIgnoreCase( server.getId() ) )
233 {
234 SettingsDecryptionResult result =
235 settingsDecrypter.decrypt( new DefaultSettingsDecryptionRequest( server ) );
236 server = result.getServer();
237
238 AuthenticationInfo authInfo = new AuthenticationInfo();
239 authInfo.setUserName( server.getUsername() );
240 authInfo.setPassword( server.getPassword() );
241 authInfo.setPrivateKey( server.getPrivateKey() );
242 authInfo.setPassphrase( server.getPassphrase() );
243
244 return authInfo;
245 }
246 }
247 }
248 }
249 }
250
251
252 return new AuthenticationInfo();
253 }
254
255 private ProxyInfo getProxy( String protocol )
256 {
257 MavenSession session = legacySupport.getSession();
258
259 if ( session != null && protocol != null )
260 {
261 MavenExecutionRequest request = session.getRequest();
262
263 if ( request != null )
264 {
265 List<Proxy> proxies = request.getProxies();
266
267 if ( proxies != null )
268 {
269 for ( Proxy proxy : proxies )
270 {
271 if ( proxy.isActive() && protocol.equalsIgnoreCase( proxy.getProtocol() ) )
272 {
273 SettingsDecryptionResult result =
274 settingsDecrypter.decrypt( new DefaultSettingsDecryptionRequest( proxy ) );
275 proxy = result.getProxy();
276
277 ProxyInfo proxyInfo = new ProxyInfo();
278 proxyInfo.setHost( proxy.getHost() );
279 proxyInfo.setType( proxy.getProtocol() );
280 proxyInfo.setPort( proxy.getPort() );
281 proxyInfo.setNonProxyHosts( proxy.getNonProxyHosts() );
282 proxyInfo.setUserName( proxy.getUsername() );
283 proxyInfo.setPassword( proxy.getPassword() );
284
285 return proxyInfo;
286 }
287 }
288 }
289 }
290 }
291
292 return null;
293 }
294
295 private Mirror getMirror( String repoId )
296 {
297 MavenSession session = legacySupport.getSession();
298
299 MavenExecutionRequest request = session.getRequest();
300
301 if ( request != null )
302 {
303 return getMirror( repoId, request.getMirrors() );
304 }
305
306 return null;
307 }
308
309 private static final String WILDCARD = "*";
310
311 private static final String EXTERNAL_WILDCARD = "external:*";
312
313 private Mirror getMirror( String repoId, List<Mirror> mirrors )
314 {
315 if ( repoId != null && mirrors != null )
316 {
317 for ( Mirror mirror : mirrors )
318 {
319 if ( repoId.equals( mirror.getMirrorOf() ) )
320 {
321 return mirror;
322 }
323 }
324
325 for ( Mirror mirror : mirrors )
326 {
327 if ( matchPattern( repoId, mirror.getMirrorOf() ) )
328 {
329 return mirror;
330 }
331 }
332 }
333
334 return null;
335 }
336
337
338
339
340
341
342
343
344
345
346 static boolean matchPattern( String originalId, String pattern )
347 {
348 boolean result = false;
349
350
351 if ( WILDCARD.equals( pattern ) || pattern.equals( originalId ) )
352 {
353 result = true;
354 }
355 else
356 {
357
358 String[] repos = pattern.split( "," );
359 for ( String repo : repos )
360 {
361
362 if ( repo.length() > 1 && repo.startsWith( "!" ) )
363 {
364 if ( repo.substring( 1 ).equals( originalId ) )
365 {
366
367 result = false;
368 break;
369 }
370 }
371
372 else if ( repo.equals( originalId ) )
373 {
374 result = true;
375 break;
376 }
377
378 else if ( EXTERNAL_WILDCARD.equals( repo ) )
379 {
380 result = true;
381
382 }
383 else if ( WILDCARD.equals( repo ) )
384 {
385 result = true;
386
387 }
388 }
389 }
390 return result;
391 }
392
393
394
395 static boolean matchesLayout( ArtifactRepository repository, Mirror mirror )
396 {
397 return matchesLayout( repository.getLayout().getId(), mirror.getMirrorOfLayouts() );
398 }
399
400
401
402
403
404
405
406
407
408 static boolean matchesLayout( String repoLayout, String mirrorLayout )
409 {
410 boolean result = false;
411
412
413 if ( StringUtils.isEmpty( mirrorLayout ) || WILDCARD.equals( mirrorLayout ) )
414 {
415 result = true;
416 }
417 else if ( mirrorLayout.equals( repoLayout ) )
418 {
419 result = true;
420 }
421 else
422 {
423
424 String[] layouts = mirrorLayout.split( "," );
425 for ( String layout : layouts )
426 {
427
428 if ( layout.length() > 1 && layout.startsWith( "!" ) )
429 {
430 if ( layout.substring( 1 ).equals( repoLayout ) )
431 {
432
433 result = false;
434 break;
435 }
436 }
437
438 else if ( layout.equals( repoLayout ) )
439 {
440 result = true;
441 break;
442 }
443 else if ( WILDCARD.equals( layout ) )
444 {
445 result = true;
446
447 }
448 }
449 }
450
451 return result;
452 }
453 }