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