1 package org.apache.maven.archetype.common;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.archetype.downloader.DownloadException;
23 import org.apache.maven.archetype.downloader.DownloadNotFoundException;
24 import org.apache.maven.archetype.downloader.Downloader;
25 import org.apache.maven.archetype.exception.UnknownArchetype;
26 import org.apache.maven.archetype.metadata.ArchetypeDescriptor;
27 import org.apache.maven.archetype.metadata.io.xpp3.ArchetypeDescriptorXpp3Reader;
28 import org.apache.maven.archetype.old.descriptor.ArchetypeDescriptorBuilder;
29 import org.apache.maven.artifact.repository.ArtifactRepository;
30 import org.apache.maven.model.Model;
31
32 import org.codehaus.plexus.component.annotations.Component;
33 import org.codehaus.plexus.component.annotations.Requirement;
34 import org.codehaus.plexus.logging.AbstractLogEnabled;
35 import org.codehaus.plexus.util.IOUtil;
36 import org.codehaus.plexus.util.ReaderFactory;
37 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
38
39 import java.io.File;
40 import java.io.IOException;
41 import java.io.InputStream;
42 import java.io.Reader;
43
44 import java.net.MalformedURLException;
45 import java.net.URL;
46 import java.net.URLClassLoader;
47
48 import java.util.ArrayList;
49 import java.util.Enumeration;
50 import java.util.List;
51 import java.util.Map;
52 import java.util.TreeMap;
53 import java.util.zip.ZipEntry;
54 import java.util.zip.ZipException;
55 import java.util.zip.ZipFile;
56
57 @Component( role = ArchetypeArtifactManager.class )
58 public class DefaultArchetypeArtifactManager
59 extends AbstractLogEnabled
60 implements ArchetypeArtifactManager
61 {
62 @Requirement
63 private Downloader downloader;
64
65 @Requirement
66 private PomManager pomManager;
67
68 private Map<String, File> archetypeCache = new TreeMap<String, File>();
69
70 public File getArchetypeFile( final String groupId, final String artifactId, final String version,
71 ArtifactRepository archetypeRepository, final ArtifactRepository localRepository,
72 final List<ArtifactRepository> repositories )
73 throws UnknownArchetype
74 {
75 try
76 {
77 File archetype = getArchetype( groupId, artifactId, version );
78
79 if ( archetype == null )
80 {
81 archetype =
82 downloader.download( groupId, artifactId, version, archetypeRepository, localRepository,
83 repositories );
84
85 setArchetype( groupId, artifactId, version, archetype );
86 }
87 return archetype;
88 }
89 catch ( DownloadNotFoundException ex )
90 {
91 throw new UnknownArchetype( ex );
92 }
93 catch ( DownloadException ex )
94 {
95 throw new UnknownArchetype( ex );
96 }
97 }
98
99 public ClassLoader getArchetypeJarLoader( File archetypeFile )
100 throws UnknownArchetype
101 {
102 try
103 {
104 URL[] urls = new URL[1];
105
106 urls[0] = archetypeFile.toURI().toURL();
107
108 return new URLClassLoader( urls );
109 }
110 catch ( MalformedURLException e )
111 {
112 throw new UnknownArchetype( e );
113 }
114 }
115
116 public Model getArchetypePom( File jar )
117 throws XmlPullParserException, UnknownArchetype, IOException
118 {
119 ZipFile zipFile = null;
120 try
121 {
122 String pomFileName = null;
123 zipFile = getArchetypeZipFile( jar );
124
125 Enumeration<? extends ZipEntry> enumeration = zipFile.entries();
126 while ( enumeration.hasMoreElements() )
127 {
128 ZipEntry el = (ZipEntry) enumeration.nextElement();
129
130 String entry = el.getName();
131 if ( entry.startsWith( "META-INF" ) && entry.endsWith( "pom.xml" ) )
132 {
133 pomFileName = entry;
134 }
135 }
136
137 if ( pomFileName == null )
138 {
139 return null;
140 }
141
142 ZipEntry pom = zipFile.getEntry( pomFileName );
143
144 if ( pom == null )
145 {
146 return null;
147 }
148 return pomManager.readPom( zipFile.getInputStream( pom ) );
149 }
150 finally
151 {
152 closeZipFile( zipFile );
153 }
154 }
155
156 public ZipFile getArchetypeZipFile( File archetypeFile )
157 throws UnknownArchetype
158 {
159 try
160 {
161 return new ZipFile( archetypeFile );
162 }
163 catch ( ZipException e )
164 {
165 throw new UnknownArchetype( e );
166 }
167 catch ( IOException e )
168 {
169 throw new UnknownArchetype( e );
170 }
171 }
172
173 public boolean isFileSetArchetype( File archetypeFile )
174 {
175 ZipFile zipFile = null;
176 try
177 {
178 getLogger().debug( "checking fileset archetype status on " + archetypeFile );
179
180 zipFile = getArchetypeZipFile( archetypeFile );
181
182 return isFileSetArchetype( zipFile );
183 }
184 catch ( IOException e )
185 {
186 getLogger().debug( e.toString() );
187 return false;
188 }
189 catch ( UnknownArchetype e )
190 {
191 getLogger().debug( e.toString() );
192 return false;
193 }
194 finally
195 {
196 closeZipFile( zipFile );
197 }
198 }
199
200 public boolean isFileSetArchetype( String groupId, String artifactId, String version,
201 ArtifactRepository archetypeRepository, ArtifactRepository localRepository,
202 List<ArtifactRepository> repositories )
203 {
204 try
205 {
206 File archetypeFile = getArchetypeFile( groupId, artifactId, version, archetypeRepository,
207 localRepository, repositories );
208
209 return isFileSetArchetype( archetypeFile );
210 }
211 catch ( UnknownArchetype e )
212 {
213 getLogger().debug( e.toString() );
214 return false;
215 }
216 }
217
218 public boolean isOldArchetype( File archetypeFile )
219 {
220 ZipFile zipFile = null;
221 try
222 {
223 getLogger().debug( "checking old archetype status on " + archetypeFile );
224
225 zipFile = getArchetypeZipFile( archetypeFile );
226
227 return isOldArchetype( zipFile );
228 }
229 catch ( IOException e )
230 {
231 getLogger().debug( e.toString() );
232 return false;
233 }
234 catch ( UnknownArchetype e )
235 {
236 getLogger().debug( e.toString() );
237 return false;
238 }
239 finally
240 {
241 closeZipFile( zipFile );
242 }
243 }
244
245 public boolean isOldArchetype( String groupId, String artifactId, String version,
246 ArtifactRepository archetypeRepository, ArtifactRepository localRepository,
247 List<ArtifactRepository> repositories )
248 {
249 try
250 {
251 File archetypeFile = getArchetypeFile( groupId, artifactId, version, archetypeRepository,
252 localRepository, repositories );
253
254 return isOldArchetype( archetypeFile );
255 }
256 catch ( UnknownArchetype e )
257 {
258 getLogger().debug( e.toString() );
259 return false;
260 }
261 }
262
263 public boolean exists( String archetypeGroupId, String archetypeArtifactId, String archetypeVersion,
264 ArtifactRepository archetypeRepository, ArtifactRepository localRepository,
265 List<ArtifactRepository> remoteRepositories )
266 {
267 try
268 {
269 File archetype = getArchetype( archetypeGroupId, archetypeArtifactId, archetypeVersion );
270 if ( archetype == null )
271 {
272 archetype =
273 downloader.download( archetypeGroupId, archetypeArtifactId, archetypeVersion, archetypeRepository,
274 localRepository, remoteRepositories );
275 setArchetype( archetypeGroupId, archetypeArtifactId, archetypeVersion, archetype );
276 }
277
278 return archetype.exists();
279 }
280 catch ( DownloadException e )
281 {
282 getLogger().debug(
283 "Archetype " + archetypeGroupId + ":" + archetypeArtifactId + ":" + archetypeVersion
284 + " doesn't exist", e );
285 return false;
286 }
287 catch ( DownloadNotFoundException e )
288 {
289 getLogger().debug(
290 "Archetype " + archetypeGroupId + ":" + archetypeArtifactId + ":" + archetypeVersion
291 + " doesn't exist", e );
292 return false;
293 }
294 }
295
296 public ArchetypeDescriptor getFileSetArchetypeDescriptor( File archetypeFile )
297 throws UnknownArchetype
298 {
299 ZipFile zipFile = null;
300 try
301 {
302 zipFile = getArchetypeZipFile( archetypeFile );
303
304 return loadFileSetArchetypeDescriptor( zipFile );
305 }
306 catch ( XmlPullParserException e )
307 {
308 throw new UnknownArchetype( e );
309 }
310 catch ( IOException e )
311 {
312 throw new UnknownArchetype( e );
313 }
314 finally
315 {
316 closeZipFile( zipFile );
317 }
318 }
319
320 public org.apache.maven.archetype.metadata.ArchetypeDescriptor getFileSetArchetypeDescriptor(
321 String groupId, String artifactId, String version, ArtifactRepository archetypeRepository,
322 ArtifactRepository localRepository, List<ArtifactRepository> repositories )
323 throws UnknownArchetype
324 {
325 File archetypeFile =
326 getArchetypeFile( groupId, artifactId, version, archetypeRepository, localRepository, repositories );
327
328 return getFileSetArchetypeDescriptor( archetypeFile );
329 }
330
331 public List<String> getFilesetArchetypeResources( File archetypeFile )
332 throws UnknownArchetype
333 {
334 getLogger().debug( "getFilesetArchetypeResources( \"" + archetypeFile.getAbsolutePath() + "\" )" );
335 List<String> archetypeResources = new ArrayList<String>();
336
337 ZipFile zipFile = null;
338 try
339 {
340 zipFile = getArchetypeZipFile( archetypeFile );
341
342 Enumeration<? extends ZipEntry> enumeration = zipFile.entries();
343 while ( enumeration.hasMoreElements() )
344 {
345 ZipEntry entry = (ZipEntry) enumeration.nextElement();
346
347 if ( entry.getName().startsWith( Constants.ARCHETYPE_RESOURCES ) )
348 {
349
350 String resource = entry.getName().substring( Constants.ARCHETYPE_RESOURCES.length() + 1 );
351 getLogger().debug( " - found resource (" + Constants.ARCHETYPE_RESOURCES + "/)" + resource );
352
353 archetypeResources.add( resource );
354 }
355 else
356 {
357 getLogger().debug( " - ignored resource " + entry.getName() );
358 }
359 }
360 return archetypeResources;
361 }
362 finally
363 {
364 closeZipFile( zipFile );
365 }
366 }
367
368 public org.apache.maven.archetype.old.descriptor.ArchetypeDescriptor getOldArchetypeDescriptor( File archetypeFile )
369 throws UnknownArchetype
370 {
371 ZipFile zipFile = null;
372 try
373 {
374 zipFile = getArchetypeZipFile( archetypeFile );
375
376 return loadOldArchetypeDescriptor( zipFile );
377 }
378 catch ( XmlPullParserException e )
379 {
380 throw new UnknownArchetype( e );
381 }
382 catch ( IOException e )
383 {
384 throw new UnknownArchetype( e );
385 }
386 finally
387 {
388 closeZipFile( zipFile );
389 }
390 }
391
392 public org.apache.maven.archetype.old.descriptor.ArchetypeDescriptor getOldArchetypeDescriptor(
393 String groupId, String artifactId, String version, ArtifactRepository archetypeRepository,
394 ArtifactRepository localRepository, List<ArtifactRepository> repositories )
395 throws UnknownArchetype
396 {
397 File archetypeFile =
398 getArchetypeFile( groupId, artifactId, version, archetypeRepository, localRepository, repositories );
399
400 return getOldArchetypeDescriptor( archetypeFile );
401 }
402
403 private File getArchetype( String archetypeGroupId, String archetypeArtifactId, String archetypeVersion )
404 {
405 String key = archetypeGroupId + ":" + archetypeArtifactId + ":" + archetypeVersion;
406
407 if ( archetypeCache.containsKey( key ) )
408 {
409 getLogger().debug( "Found archetype " + key + " in cache: " + archetypeCache.get( key ) );
410
411 return archetypeCache.get( key );
412 }
413
414 getLogger().debug( "Not found archetype " + key + " in cache" );
415 return null;
416 }
417
418 private void setArchetype( String archetypeGroupId, String archetypeArtifactId, String archetypeVersion,
419 File archetype )
420 {
421 String key = archetypeGroupId + ":" + archetypeArtifactId + ":" + archetypeVersion;
422
423 archetypeCache.put( key, archetype );
424 }
425
426 private boolean isFileSetArchetype( ZipFile zipFile )
427 throws IOException
428 {
429 Reader reader = null;
430 try
431 {
432 reader = getArchetypeDescriptorReader( zipFile );
433
434 return ( reader != null );
435 }
436 finally
437 {
438 IOUtil.close( reader );
439 }
440 }
441
442 private boolean isOldArchetype( ZipFile zipFile )
443 throws IOException
444 {
445 Reader reader = null;
446 try
447 {
448 reader = getOldArchetypeDescriptorReader( zipFile );
449
450 return ( reader != null );
451 }
452 finally
453 {
454 IOUtil.close( reader );
455 }
456 }
457
458 private org.apache.maven.archetype.metadata.ArchetypeDescriptor loadFileSetArchetypeDescriptor( ZipFile zipFile )
459 throws IOException, XmlPullParserException
460 {
461 Reader reader = null;
462 try
463 {
464 reader = getArchetypeDescriptorReader( zipFile );
465
466 if ( reader == null )
467 {
468 return null;
469 }
470
471 ArchetypeDescriptorXpp3Reader archetypeReader = new ArchetypeDescriptorXpp3Reader();
472 return archetypeReader.read( reader, false );
473 }
474 catch ( IOException e )
475 {
476 throw e;
477 }
478 catch ( XmlPullParserException e )
479 {
480 throw e;
481 }
482 finally
483 {
484 IOUtil.close( reader );
485 }
486 }
487
488 private org.apache.maven.archetype.old.descriptor.ArchetypeDescriptor loadOldArchetypeDescriptor( ZipFile zipFile )
489 throws IOException, XmlPullParserException
490 {
491 Reader reader = null;
492 try
493 {
494 reader = getOldArchetypeDescriptorReader( zipFile );
495
496 if ( reader == null )
497 {
498 return null;
499 }
500
501 ArchetypeDescriptorBuilder builder = new ArchetypeDescriptorBuilder();
502 return builder.build( reader );
503 }
504 catch ( IOException ex )
505 {
506 throw ex;
507 }
508 catch ( XmlPullParserException ex )
509 {
510 throw ex;
511 }
512 finally
513 {
514 IOUtil.close( reader );
515 }
516 }
517
518 private Reader getArchetypeDescriptorReader( ZipFile zipFile )
519 throws IOException
520 {
521 return getDescriptorReader( zipFile, Constants.ARCHETYPE_DESCRIPTOR );
522 }
523
524 private Reader getOldArchetypeDescriptorReader( ZipFile zipFile )
525 throws IOException
526 {
527 Reader reader = getDescriptorReader( zipFile, Constants.OLD_ARCHETYPE_DESCRIPTOR );
528
529 if ( reader == null )
530 {
531 reader = getDescriptorReader( zipFile, Constants.OLDER_ARCHETYPE_DESCRIPTOR );
532 }
533
534 return reader;
535 }
536
537 private Reader getDescriptorReader( ZipFile zipFile, String descriptor )
538 throws IOException
539 {
540 ZipEntry entry = searchEntry( zipFile, descriptor );
541
542 if ( entry == null )
543 {
544 return null;
545 }
546
547 InputStream is = zipFile.getInputStream( entry );
548
549 if ( is == null )
550 {
551 throw new IOException( "The " + descriptor + " descriptor cannot be read in " + zipFile.getName() + "." );
552 }
553
554 return ReaderFactory.newXmlReader( is );
555 }
556
557 private ZipEntry searchEntry( ZipFile zipFile, String searchString )
558 {
559 getLogger().debug( "Searching for " + searchString + " inside " + zipFile.getName() );
560
561 Enumeration<? extends ZipEntry> enu = zipFile.entries();
562 while ( enu.hasMoreElements() )
563 {
564 ZipEntry entryfound = (ZipEntry) enu.nextElement();
565 getLogger().debug( " - " + entryfound.getName() );
566
567 if ( searchString.equals( entryfound.getName() ) )
568 {
569 getLogger().debug( "Entry found" );
570 return entryfound;
571 }
572 }
573 return null;
574 }
575
576 private void closeZipFile( ZipFile zipFile )
577 {
578 try
579 {
580 zipFile.close();
581 }
582 catch ( Exception e )
583 {
584 getLogger().error( "Failed to close " + zipFile.getName() + " zipFile." );
585 }
586 }
587 }