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 if ( zipFile != null )
197 {
198 closeZipFile( zipFile );
199 }
200 }
201 }
202
203 public boolean isFileSetArchetype( String groupId, String artifactId, String version,
204 ArtifactRepository archetypeRepository, ArtifactRepository localRepository,
205 List<ArtifactRepository> repositories )
206 {
207 try
208 {
209 File archetypeFile = getArchetypeFile( groupId, artifactId, version, archetypeRepository,
210 localRepository, repositories );
211
212 return isFileSetArchetype( archetypeFile );
213 }
214 catch ( UnknownArchetype e )
215 {
216 getLogger().debug( e.toString() );
217 return false;
218 }
219 }
220
221 public boolean isOldArchetype( File archetypeFile )
222 {
223 ZipFile zipFile = null;
224 try
225 {
226 getLogger().debug( "checking old archetype status on " + archetypeFile );
227
228 zipFile = getArchetypeZipFile( archetypeFile );
229
230 return isOldArchetype( zipFile );
231 }
232 catch ( IOException e )
233 {
234 getLogger().debug( e.toString() );
235 return false;
236 }
237 catch ( UnknownArchetype e )
238 {
239 getLogger().debug( e.toString() );
240 return false;
241 }
242 finally
243 {
244 if ( zipFile != null )
245 {
246 closeZipFile( zipFile );
247 }
248 }
249 }
250
251 public boolean isOldArchetype( String groupId, String artifactId, String version,
252 ArtifactRepository archetypeRepository, ArtifactRepository localRepository,
253 List<ArtifactRepository> repositories )
254 {
255 try
256 {
257 File archetypeFile = getArchetypeFile( groupId, artifactId, version, archetypeRepository,
258 localRepository, repositories );
259
260 return isOldArchetype( archetypeFile );
261 }
262 catch ( UnknownArchetype e )
263 {
264 getLogger().debug( e.toString() );
265 return false;
266 }
267 }
268
269 public boolean exists( String archetypeGroupId, String archetypeArtifactId, String archetypeVersion,
270 ArtifactRepository archetypeRepository, ArtifactRepository localRepository,
271 List<ArtifactRepository> remoteRepositories )
272 {
273 try
274 {
275 File archetype = getArchetype( archetypeGroupId, archetypeArtifactId, archetypeVersion );
276 if ( archetype == null )
277 {
278 archetype =
279 downloader.download( archetypeGroupId, archetypeArtifactId, archetypeVersion, archetypeRepository,
280 localRepository, remoteRepositories );
281 setArchetype( archetypeGroupId, archetypeArtifactId, archetypeVersion, archetype );
282 }
283
284 return archetype.exists();
285 }
286 catch ( DownloadException e )
287 {
288 getLogger().debug(
289 "Archetype " + archetypeGroupId + ":" + archetypeArtifactId + ":" + archetypeVersion
290 + " doesn't exist", e );
291 return false;
292 }
293 catch ( DownloadNotFoundException e )
294 {
295 getLogger().debug(
296 "Archetype " + archetypeGroupId + ":" + archetypeArtifactId + ":" + archetypeVersion
297 + " doesn't exist", e );
298 return false;
299 }
300 }
301
302 public ArchetypeDescriptor getFileSetArchetypeDescriptor( File archetypeFile )
303 throws UnknownArchetype
304 {
305 ZipFile zipFile = null;
306 try
307 {
308 zipFile = getArchetypeZipFile( archetypeFile );
309
310 return loadFileSetArchetypeDescriptor( zipFile );
311 }
312 catch ( XmlPullParserException e )
313 {
314 throw new UnknownArchetype( e );
315 }
316 catch ( IOException e )
317 {
318 throw new UnknownArchetype( e );
319 }
320 finally
321 {
322 closeZipFile( zipFile );
323 }
324 }
325
326 public org.apache.maven.archetype.metadata.ArchetypeDescriptor getFileSetArchetypeDescriptor(
327 String groupId, String artifactId, String version, ArtifactRepository archetypeRepository,
328 ArtifactRepository localRepository, List<ArtifactRepository> repositories )
329 throws UnknownArchetype
330 {
331 File archetypeFile =
332 getArchetypeFile( groupId, artifactId, version, archetypeRepository, localRepository, repositories );
333
334 return getFileSetArchetypeDescriptor( archetypeFile );
335 }
336
337 public List<String> getFilesetArchetypeResources( File archetypeFile )
338 throws UnknownArchetype
339 {
340 getLogger().debug( "getFilesetArchetypeResources( \"" + archetypeFile.getAbsolutePath() + "\" )" );
341 List<String> archetypeResources = new ArrayList<String>();
342
343 ZipFile zipFile = null;
344 try
345 {
346 zipFile = getArchetypeZipFile( archetypeFile );
347
348 Enumeration<? extends ZipEntry> enumeration = zipFile.entries();
349 while ( enumeration.hasMoreElements() )
350 {
351 ZipEntry entry = (ZipEntry) enumeration.nextElement();
352
353 if ( entry.getName().startsWith( Constants.ARCHETYPE_RESOURCES ) )
354 {
355
356 String resource = entry.getName().substring( Constants.ARCHETYPE_RESOURCES.length() + 1 );
357 getLogger().debug( " - found resource (" + Constants.ARCHETYPE_RESOURCES + "/)" + resource );
358
359 archetypeResources.add( resource );
360 }
361 else
362 {
363 getLogger().debug( " - ignored resource " + entry.getName() );
364 }
365 }
366 return archetypeResources;
367 }
368 finally
369 {
370 closeZipFile( zipFile );
371 }
372 }
373
374 public org.apache.maven.archetype.old.descriptor.ArchetypeDescriptor getOldArchetypeDescriptor( File archetypeFile )
375 throws UnknownArchetype
376 {
377 ZipFile zipFile = null;
378 try
379 {
380 zipFile = getArchetypeZipFile( archetypeFile );
381
382 return loadOldArchetypeDescriptor( zipFile );
383 }
384 catch ( XmlPullParserException e )
385 {
386 throw new UnknownArchetype( e );
387 }
388 catch ( IOException e )
389 {
390 throw new UnknownArchetype( e );
391 }
392 finally
393 {
394 closeZipFile( zipFile );
395 }
396 }
397
398 public org.apache.maven.archetype.old.descriptor.ArchetypeDescriptor getOldArchetypeDescriptor(
399 String groupId, String artifactId, String version, ArtifactRepository archetypeRepository,
400 ArtifactRepository localRepository, List<ArtifactRepository> repositories )
401 throws UnknownArchetype
402 {
403 File archetypeFile =
404 getArchetypeFile( groupId, artifactId, version, archetypeRepository, localRepository, repositories );
405
406 return getOldArchetypeDescriptor( archetypeFile );
407 }
408
409 private File getArchetype( String archetypeGroupId, String archetypeArtifactId, String archetypeVersion )
410 {
411 String key = archetypeGroupId + ":" + archetypeArtifactId + ":" + archetypeVersion;
412
413 if ( archetypeCache.containsKey( key ) )
414 {
415 getLogger().debug( "Found archetype " + key + " in cache: " + archetypeCache.get( key ) );
416
417 return archetypeCache.get( key );
418 }
419
420 getLogger().debug( "Not found archetype " + key + " in cache" );
421 return null;
422 }
423
424 private void setArchetype( String archetypeGroupId, String archetypeArtifactId, String archetypeVersion,
425 File archetype )
426 {
427 String key = archetypeGroupId + ":" + archetypeArtifactId + ":" + archetypeVersion;
428
429 archetypeCache.put( key, archetype );
430 }
431
432 private boolean isFileSetArchetype( ZipFile zipFile )
433 throws IOException
434 {
435 Reader reader = null;
436 try
437 {
438 reader = getArchetypeDescriptorReader( zipFile );
439
440 return ( reader != null );
441 }
442 finally
443 {
444 IOUtil.close( reader );
445 }
446 }
447
448 private boolean isOldArchetype( ZipFile zipFile )
449 throws IOException
450 {
451 Reader reader = null;
452 try
453 {
454 reader = getOldArchetypeDescriptorReader( zipFile );
455
456 return ( reader != null );
457 }
458 finally
459 {
460 IOUtil.close( reader );
461 }
462 }
463
464 private org.apache.maven.archetype.metadata.ArchetypeDescriptor loadFileSetArchetypeDescriptor( ZipFile zipFile )
465 throws IOException, XmlPullParserException
466 {
467 Reader reader = null;
468 try
469 {
470 reader = getArchetypeDescriptorReader( zipFile );
471
472 if ( reader == null )
473 {
474 return null;
475 }
476
477 ArchetypeDescriptorXpp3Reader archetypeReader = new ArchetypeDescriptorXpp3Reader();
478 return archetypeReader.read( reader, false );
479 }
480 catch ( IOException e )
481 {
482 throw e;
483 }
484 catch ( XmlPullParserException e )
485 {
486 throw e;
487 }
488 finally
489 {
490 IOUtil.close( reader );
491 }
492 }
493
494 private org.apache.maven.archetype.old.descriptor.ArchetypeDescriptor loadOldArchetypeDescriptor( ZipFile zipFile )
495 throws IOException, XmlPullParserException
496 {
497 Reader reader = null;
498 try
499 {
500 reader = getOldArchetypeDescriptorReader( zipFile );
501
502 if ( reader == null )
503 {
504 return null;
505 }
506
507 ArchetypeDescriptorBuilder builder = new ArchetypeDescriptorBuilder();
508 return builder.build( reader );
509 }
510 catch ( IOException ex )
511 {
512 throw ex;
513 }
514 catch ( XmlPullParserException ex )
515 {
516 throw ex;
517 }
518 finally
519 {
520 IOUtil.close( reader );
521 }
522 }
523
524 private Reader getArchetypeDescriptorReader( ZipFile zipFile )
525 throws IOException
526 {
527 return getDescriptorReader( zipFile, Constants.ARCHETYPE_DESCRIPTOR );
528 }
529
530 private Reader getOldArchetypeDescriptorReader( ZipFile zipFile )
531 throws IOException
532 {
533 Reader reader = getDescriptorReader( zipFile, Constants.OLD_ARCHETYPE_DESCRIPTOR );
534
535 if ( reader == null )
536 {
537 reader = getDescriptorReader( zipFile, Constants.OLDER_ARCHETYPE_DESCRIPTOR );
538 }
539
540 return reader;
541 }
542
543 private Reader getDescriptorReader( ZipFile zipFile, String descriptor )
544 throws IOException
545 {
546 ZipEntry entry = searchEntry( zipFile, descriptor );
547
548 if ( entry == null )
549 {
550 return null;
551 }
552
553 InputStream is = zipFile.getInputStream( entry );
554
555 if ( is == null )
556 {
557 throw new IOException( "The " + descriptor + " descriptor cannot be read in " + zipFile.getName() + "." );
558 }
559
560 return ReaderFactory.newXmlReader( is );
561 }
562
563 private ZipEntry searchEntry( ZipFile zipFile, String searchString )
564 {
565 getLogger().debug( "Searching for " + searchString + " inside " + zipFile.getName() );
566
567 Enumeration<? extends ZipEntry> enu = zipFile.entries();
568 while ( enu.hasMoreElements() )
569 {
570 ZipEntry entryfound = (ZipEntry) enu.nextElement();
571 getLogger().debug( " - " + entryfound.getName() );
572
573 if ( searchString.equals( entryfound.getName() ) )
574 {
575 getLogger().debug( "Entry found" );
576 return entryfound;
577 }
578 }
579 return null;
580 }
581
582 private void closeZipFile( ZipFile zipFile )
583 {
584 try
585 {
586 zipFile.close();
587 }
588 catch ( Exception e )
589 {
590 getLogger().error( "Failed to close " + zipFile.getName() + " zipFile." );
591 }
592 }
593 }