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 public void updateCatalog( ProjectBuildingRequest buildingRequest, Archetype archetype )
142 throws ArchetypeDataSourceException
143 {
144 throw new ArchetypeDataSourceException( "Not supported yet." );
145 }
146
147 private ArchetypeCatalog downloadCatalog( ArtifactRepository repository )
148 throws WagonException, IOException, ArchetypeDataSourceException
149 {
150 getLogger().debug( "Searching for remote catalog: " + repository.getUrl() + "/" + ARCHETYPE_CATALOG_FILENAME );
151
152
153 Repository wagonRepository = new Repository( repository.getId(), repository.getUrl() );
154
155 AuthenticationInfo authInfo = getAuthenticationInfo( wagonRepository.getId() );
156 ProxyInfo proxyInfo = getProxy( wagonRepository.getProtocol() );
157
158 Wagon wagon = getWagon( wagonRepository );
159
160 File catalog = File.createTempFile( "archetype-catalog", ".xml" );
161 try
162 {
163 wagon.connect( wagonRepository, authInfo, proxyInfo );
164 wagon.get( ARCHETYPE_CATALOG_FILENAME, catalog );
165
166 return readCatalog( ReaderFactory.newXmlReader( catalog ) );
167 }
168 finally
169 {
170 disconnectWagon( wagon );
171 catalog.delete();
172 }
173 }
174
175 private void disconnectWagon( Wagon wagon )
176 {
177 try
178 {
179 wagon.disconnect();
180 }
181 catch ( Exception e )
182 {
183 getLogger().warn( "Problem disconnecting from wagon - ignoring: " + e.getMessage() );
184 }
185 }
186
187
188
189 private Wagon getWagon( Repository repository )
190 throws UnsupportedProtocolException
191 {
192 return getWagon( repository.getProtocol() );
193 }
194
195 private Wagon getWagon( String protocol )
196 throws UnsupportedProtocolException
197 {
198 if ( protocol == null )
199 {
200 throw new UnsupportedProtocolException( "Unspecified protocol" );
201 }
202
203 String hint = protocol.toLowerCase( java.util.Locale.ENGLISH );
204
205 Wagon wagon = wagons.get( hint );
206 if ( wagon == null )
207 {
208 throw new UnsupportedProtocolException( "Cannot find wagon which supports the requested protocol: "
209 + protocol );
210 }
211
212 return wagon;
213 }
214
215 private AuthenticationInfo getAuthenticationInfo( String id )
216 {
217 MavenSession session = legacySupport.getSession();
218
219 if ( session != null && id != null )
220 {
221 MavenExecutionRequest request = session.getRequest();
222
223 if ( request != null )
224 {
225 List<Server> servers = request.getServers();
226
227 if ( servers != null )
228 {
229 for ( Server server : servers )
230 {
231 if ( id.equalsIgnoreCase( server.getId() ) )
232 {
233 SettingsDecryptionResult result =
234 settingsDecrypter.decrypt( new DefaultSettingsDecryptionRequest( server ) );
235 server = result.getServer();
236
237 AuthenticationInfo authInfo = new AuthenticationInfo();
238 authInfo.setUserName( server.getUsername() );
239 authInfo.setPassword( server.getPassword() );
240 authInfo.setPrivateKey( server.getPrivateKey() );
241 authInfo.setPassphrase( server.getPassphrase() );
242
243 return authInfo;
244 }
245 }
246 }
247 }
248 }
249
250
251 return new AuthenticationInfo();
252 }
253
254 private ProxyInfo getProxy( String protocol )
255 {
256 MavenSession session = legacySupport.getSession();
257
258 if ( session != null && protocol != null )
259 {
260 MavenExecutionRequest request = session.getRequest();
261
262 if ( request != null )
263 {
264 List<Proxy> proxies = request.getProxies();
265
266 if ( proxies != null )
267 {
268 for ( Proxy proxy : proxies )
269 {
270 if ( proxy.isActive() && protocol.equalsIgnoreCase( proxy.getProtocol() ) )
271 {
272 SettingsDecryptionResult result =
273 settingsDecrypter.decrypt( new DefaultSettingsDecryptionRequest( proxy ) );
274 proxy = result.getProxy();
275
276 ProxyInfo proxyInfo = new ProxyInfo();
277 proxyInfo.setHost( proxy.getHost() );
278 proxyInfo.setType( proxy.getProtocol() );
279 proxyInfo.setPort( proxy.getPort() );
280 proxyInfo.setNonProxyHosts( proxy.getNonProxyHosts() );
281 proxyInfo.setUserName( proxy.getUsername() );
282 proxyInfo.setPassword( proxy.getPassword() );
283
284 return proxyInfo;
285 }
286 }
287 }
288 }
289 }
290
291 return null;
292 }
293
294 private Mirror getMirror( String repoId )
295 {
296 MavenSession session = legacySupport.getSession();
297
298 MavenExecutionRequest request = session.getRequest();
299
300 if ( request != null )
301 {
302 return getMirror( repoId, request.getMirrors() );
303 }
304
305 return null;
306 }
307
308 private static final String WILDCARD = "*";
309
310 private static final String EXTERNAL_WILDCARD = "external:*";
311
312 private Mirror getMirror( String repoId, List<Mirror> mirrors )
313 {
314 if ( repoId != null && mirrors != null )
315 {
316 for ( Mirror mirror : mirrors )
317 {
318 if ( repoId.equals( mirror.getMirrorOf() ) )
319 {
320 return mirror;
321 }
322 }
323
324 for ( Mirror mirror : mirrors )
325 {
326 if ( matchPattern( repoId, mirror.getMirrorOf() ) )
327 {
328 return mirror;
329 }
330 }
331 }
332
333 return null;
334 }
335
336
337
338
339
340
341
342
343
344
345 static boolean matchPattern( String originalId, String pattern )
346 {
347 boolean result = false;
348
349
350 if ( WILDCARD.equals( pattern ) || pattern.equals( originalId ) )
351 {
352 result = true;
353 }
354 else
355 {
356
357 String[] repos = pattern.split( "," );
358 for ( String repo : repos )
359 {
360
361 if ( repo.length() > 1 && repo.startsWith( "!" ) )
362 {
363 if ( repo.substring( 1 ).equals( originalId ) )
364 {
365
366 result = false;
367 break;
368 }
369 }
370
371 else if ( repo.equals( originalId ) )
372 {
373 result = true;
374 break;
375 }
376
377 else if ( EXTERNAL_WILDCARD.equals( repo ) )
378 {
379 result = true;
380
381 }
382 else if ( WILDCARD.equals( repo ) )
383 {
384 result = true;
385
386 }
387 }
388 }
389 return result;
390 }
391
392
393
394 static boolean matchesLayout( ArtifactRepository repository, Mirror mirror )
395 {
396 return matchesLayout( repository.getLayout().getId(), mirror.getMirrorOfLayouts() );
397 }
398
399
400
401
402
403
404
405
406
407 static boolean matchesLayout( String repoLayout, String mirrorLayout )
408 {
409 boolean result = false;
410
411
412 if ( StringUtils.isEmpty( mirrorLayout ) || WILDCARD.equals( mirrorLayout ) )
413 {
414 result = true;
415 }
416 else if ( mirrorLayout.equals( repoLayout ) )
417 {
418 result = true;
419 }
420 else
421 {
422
423 String[] layouts = mirrorLayout.split( "," );
424 for ( String layout : layouts )
425 {
426
427 if ( layout.length() > 1 && layout.startsWith( "!" ) )
428 {
429 if ( layout.substring( 1 ).equals( repoLayout ) )
430 {
431
432 result = false;
433 break;
434 }
435 }
436
437 else if ( layout.equals( repoLayout ) )
438 {
439 result = true;
440 break;
441 }
442 else if ( WILDCARD.equals( layout ) )
443 {
444 result = true;
445
446 }
447 }
448 }
449
450 return result;
451 }
452 }