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