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.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.ZipFile;
55
56 @Component( role = ArchetypeArtifactManager.class )
57 public class DefaultArchetypeArtifactManager
58 extends AbstractLogEnabled
59 implements ArchetypeArtifactManager
60 {
61 @Requirement
62 private Downloader downloader;
63
64 @Requirement
65 private PomManager pomManager;
66
67 private Map<String, File> archetypeCache = new TreeMap<>();
68
69 @Override
70 public File getArchetypeFile( final String groupId, final String artifactId, final String version,
71 ArtifactRepository archetypeRepository, final ArtifactRepository localRepository,
72 final List<ArtifactRepository> repositories, ProjectBuildingRequest buildingRequest )
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, buildingRequest );
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 @Override
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 @Override
118 public Model getArchetypePom( File jar )
119 throws XmlPullParserException, UnknownArchetype, IOException
120 {
121
122 try ( ZipFile zipFile = getArchetypeZipFile( jar ) )
123 {
124 String pomFileName = null;
125
126 Enumeration<? extends ZipEntry> enumeration = zipFile.entries();
127 while ( enumeration.hasMoreElements() )
128 {
129 ZipEntry el = 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 }
152
153 @Override
154 public ZipFile getArchetypeZipFile( File archetypeFile )
155 throws UnknownArchetype
156 {
157 try
158 {
159 return new ZipFile( archetypeFile );
160 }
161 catch ( IOException e )
162 {
163 throw new UnknownArchetype( e );
164 }
165 }
166
167 @Override
168 public boolean isFileSetArchetype( File archetypeFile )
169 {
170 getLogger().debug( "checking fileset archetype status on " + archetypeFile );
171
172 try ( ZipFile zipFile = getArchetypeZipFile( archetypeFile ) )
173 {
174 return isFileSetArchetype( zipFile );
175 }
176 catch ( IOException | UnknownArchetype e )
177 {
178 getLogger().debug( e.toString() );
179 return false;
180 }
181 }
182
183 @Override
184 public boolean isFileSetArchetype( String groupId, String artifactId, String version,
185 ArtifactRepository archetypeRepository, ArtifactRepository localRepository,
186 List<ArtifactRepository> repositories, ProjectBuildingRequest buildingRequest )
187 {
188 try
189 {
190 File archetypeFile = getArchetypeFile( groupId, artifactId, version, archetypeRepository,
191 localRepository, repositories, buildingRequest );
192
193 return isFileSetArchetype( archetypeFile );
194 }
195 catch ( UnknownArchetype e )
196 {
197 getLogger().debug( e.toString() );
198 return false;
199 }
200 }
201
202 @Override
203 public boolean isOldArchetype( File archetypeFile )
204 {
205 getLogger().debug( "checking old archetype status on " + archetypeFile );
206
207 try ( ZipFile zipFile = getArchetypeZipFile( archetypeFile ) )
208 {
209 return isOldArchetype( zipFile );
210 }
211 catch ( IOException | UnknownArchetype e )
212 {
213 getLogger().debug( e.toString() );
214 return false;
215 }
216 }
217
218 @Override
219 public boolean isOldArchetype( String groupId, String artifactId, String version,
220 ArtifactRepository archetypeRepository, ArtifactRepository localRepository,
221 List<ArtifactRepository> repositories, ProjectBuildingRequest buildingRequest )
222 {
223 try
224 {
225 File archetypeFile = getArchetypeFile( groupId, artifactId, version, archetypeRepository,
226 localRepository, repositories, buildingRequest );
227
228 return isOldArchetype( archetypeFile );
229 }
230 catch ( UnknownArchetype e )
231 {
232 getLogger().debug( e.toString() );
233 return false;
234 }
235 }
236
237 @Override
238 public boolean exists( String archetypeGroupId, String archetypeArtifactId, String archetypeVersion,
239 ArtifactRepository archetypeRepository, ArtifactRepository localRepository,
240 List<ArtifactRepository> remoteRepositories, ProjectBuildingRequest buildingRequest )
241 {
242 try
243 {
244 File archetype = getArchetype( archetypeGroupId, archetypeArtifactId, archetypeVersion );
245 if ( archetype == null )
246 {
247 archetype =
248 downloader.download( archetypeGroupId, archetypeArtifactId, archetypeVersion, archetypeRepository,
249 localRepository, remoteRepositories, buildingRequest );
250 setArchetype( archetypeGroupId, archetypeArtifactId, archetypeVersion, archetype );
251 }
252
253 return archetype.exists();
254 }
255 catch ( DownloadException e )
256 {
257 getLogger().debug(
258 "Archetype " + archetypeGroupId + ":" + archetypeArtifactId + ":" + archetypeVersion
259 + " doesn't exist", e );
260 return false;
261 }
262 catch ( DownloadNotFoundException e )
263 {
264 getLogger().debug(
265 "Archetype " + archetypeGroupId + ":" + archetypeArtifactId + ":" + archetypeVersion
266 + " doesn't exist", e );
267 return false;
268 }
269 }
270
271 @Override
272 public String getPostGenerationScript( File archetypeFile ) throws UnknownArchetype
273 {
274 try ( ZipFile zipFile = getArchetypeZipFile( archetypeFile ) )
275 {
276 Reader reader = getDescriptorReader( zipFile, Constants.ARCHETYPE_POST_GENERATION_SCRIPT );
277 return reader == null ? null : IOUtils.toString( reader );
278 }
279 catch ( IOException e )
280 {
281 throw new UnknownArchetype( e );
282 }
283 }
284
285 @Override
286 public ArchetypeDescriptor getFileSetArchetypeDescriptor( File archetypeFile )
287 throws UnknownArchetype
288 {
289 try ( ZipFile zipFile = getArchetypeZipFile( archetypeFile ) )
290 {
291 return loadFileSetArchetypeDescriptor( zipFile );
292 }
293 catch ( XmlPullParserException | IOException e )
294 {
295 throw new UnknownArchetype( e );
296 }
297 }
298
299 @Override
300 public org.apache.maven.archetype.metadata.ArchetypeDescriptor getFileSetArchetypeDescriptor( String groupId,
301 String artifactId,
302 String version,
303 ArtifactRepository archetypeRepository,
304 ArtifactRepository localRepository,
305 List<ArtifactRepository> repositories,
306 ProjectBuildingRequest buildingRequest )
307 throws UnknownArchetype
308 {
309 File archetypeFile = getArchetypeFile( groupId, artifactId, version, archetypeRepository, localRepository,
310 repositories, buildingRequest );
311
312 return getFileSetArchetypeDescriptor( archetypeFile );
313 }
314
315 @Override
316 public List<String> getFilesetArchetypeResources( File archetypeFile )
317 throws UnknownArchetype
318 {
319 getLogger().debug( "getFilesetArchetypeResources( \"" + archetypeFile.getAbsolutePath() + "\" )" );
320 List<String> archetypeResources = new ArrayList<>();
321
322 try ( ZipFile zipFile = getArchetypeZipFile( archetypeFile ) )
323 {
324 Enumeration<? extends ZipEntry> enumeration = zipFile.entries();
325 while ( enumeration.hasMoreElements() )
326 {
327 ZipEntry entry = enumeration.nextElement();
328
329 if ( entry.getName().startsWith( Constants.ARCHETYPE_RESOURCES ) )
330 {
331
332 String resource = entry.getName().substring( Constants.ARCHETYPE_RESOURCES.length() + 1 );
333 getLogger().debug( " - found resource (" + Constants.ARCHETYPE_RESOURCES + "/)" + resource );
334
335 archetypeResources.add( resource );
336 }
337 else
338 {
339 getLogger().debug( " - ignored resource " + entry.getName() );
340 }
341 }
342 return archetypeResources;
343 }
344 catch ( IOException e )
345 {
346 throw new UnknownArchetype( e );
347 }
348 }
349
350 @Override
351 public org.apache.maven.archetype.old.descriptor.ArchetypeDescriptor getOldArchetypeDescriptor( File archetypeFile )
352 throws UnknownArchetype
353 {
354 try ( ZipFile zipFile = getArchetypeZipFile( archetypeFile ) )
355 {
356 return loadOldArchetypeDescriptor( zipFile );
357 }
358 catch ( XmlPullParserException | IOException e )
359 {
360 throw new UnknownArchetype( e );
361 }
362 }
363
364 @Override
365 public org.apache.maven.archetype.old.descriptor.ArchetypeDescriptor getOldArchetypeDescriptor( String groupId,
366 String artifactId,
367 String version,
368 ArtifactRepository archetypeRepository,
369 ArtifactRepository localRepository,
370 List<ArtifactRepository> repositories,
371 ProjectBuildingRequest buildingRequest )
372 throws UnknownArchetype
373 {
374 File archetypeFile = getArchetypeFile( groupId, artifactId, version, archetypeRepository, localRepository,
375 repositories, buildingRequest );
376
377 return getOldArchetypeDescriptor( archetypeFile );
378 }
379
380 private File getArchetype( String archetypeGroupId, String archetypeArtifactId, String archetypeVersion )
381 {
382 String key = archetypeGroupId + ":" + archetypeArtifactId + ":" + archetypeVersion;
383
384 if ( archetypeCache.containsKey( key ) )
385 {
386 getLogger().debug( "Found archetype " + key + " in cache: " + archetypeCache.get( key ) );
387
388 return archetypeCache.get( key );
389 }
390
391 getLogger().debug( "Not found archetype " + key + " in cache" );
392 return null;
393 }
394
395 private void setArchetype( String archetypeGroupId, String archetypeArtifactId, String archetypeVersion,
396 File archetype )
397 {
398 String key = archetypeGroupId + ":" + archetypeArtifactId + ":" + archetypeVersion;
399
400 archetypeCache.put( key, archetype );
401 }
402
403 private boolean isFileSetArchetype( ZipFile zipFile )
404 throws IOException
405 {
406 try ( Reader reader = getArchetypeDescriptorReader( zipFile ); )
407 {
408 return ( reader != null );
409 }
410 }
411
412 private boolean isOldArchetype( ZipFile zipFile )
413 throws IOException
414 {
415 try ( Reader reader = getOldArchetypeDescriptorReader( zipFile ) )
416 {
417 return ( reader != null );
418 }
419 }
420
421 private org.apache.maven.archetype.metadata.ArchetypeDescriptor loadFileSetArchetypeDescriptor( ZipFile zipFile )
422 throws IOException, XmlPullParserException
423 {
424
425 try ( Reader reader = getArchetypeDescriptorReader( zipFile ) )
426 {
427 if ( reader == null )
428 {
429 return null;
430 }
431
432 ArchetypeDescriptorXpp3Reader archetypeReader = new ArchetypeDescriptorXpp3Reader();
433 return archetypeReader.read( reader, false );
434 }
435 catch ( IOException | XmlPullParserException e )
436 {
437 throw e;
438 }
439 }
440
441 private org.apache.maven.archetype.old.descriptor.ArchetypeDescriptor loadOldArchetypeDescriptor( ZipFile zipFile )
442 throws IOException, XmlPullParserException
443 {
444 try ( Reader reader = getOldArchetypeDescriptorReader( zipFile ) )
445 {
446 if ( reader == null )
447 {
448 return null;
449 }
450
451 ArchetypeDescriptorBuilder builder = new ArchetypeDescriptorBuilder();
452 return builder.build( reader );
453 }
454 catch ( IOException | XmlPullParserException ex )
455 {
456 throw ex;
457 }
458 }
459
460 private Reader getArchetypeDescriptorReader( ZipFile zipFile )
461 throws IOException
462 {
463 return getDescriptorReader( zipFile, Constants.ARCHETYPE_DESCRIPTOR );
464 }
465
466 private Reader getOldArchetypeDescriptorReader( ZipFile zipFile )
467 throws IOException
468 {
469 Reader reader = getDescriptorReader( zipFile, Constants.OLD_ARCHETYPE_DESCRIPTOR );
470
471 if ( reader == null )
472 {
473 reader = getDescriptorReader( zipFile, Constants.OLDER_ARCHETYPE_DESCRIPTOR );
474 }
475
476 return reader;
477 }
478
479 private Reader getDescriptorReader( ZipFile zipFile, String descriptor )
480 throws IOException
481 {
482 ZipEntry entry = searchEntry( zipFile, descriptor );
483
484 if ( entry == null )
485 {
486 return null;
487 }
488
489 InputStream is = zipFile.getInputStream( entry );
490
491 if ( is == null )
492 {
493 throw new IOException( "The " + descriptor + " descriptor cannot be read in " + zipFile.getName() + "." );
494 }
495
496 return ReaderFactory.newReader( is, ReaderFactory.UTF_8 );
497 }
498
499 private ZipEntry searchEntry( ZipFile zipFile, String searchString )
500 {
501 getLogger().debug( "Searching for " + searchString + " inside " + zipFile.getName() );
502
503 Enumeration<? extends ZipEntry> enu = zipFile.entries();
504 while ( enu.hasMoreElements() )
505 {
506 ZipEntry entryfound = enu.nextElement();
507 getLogger().debug( " - " + entryfound.getName() );
508
509 if ( searchString.equals( entryfound.getName() ) )
510 {
511 getLogger().debug( "Entry found" );
512 return entryfound;
513 }
514 }
515 return null;
516 }
517
518 }