View Javadoc
1   package org.apache.maven.archetype.common;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
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                     // not supposed to be file.separator
356                     String resource = entry.getName().substring( Constants.ARCHETYPE_RESOURCES.length() + 1 );
357                     getLogger().debug( "  - found resource (" + Constants.ARCHETYPE_RESOURCES + "/)" + resource );
358                     // TODO:FIXME
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 }