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.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   * @plexus.component
57   */
58  public class DefaultArchetypeArtifactManager
59      extends AbstractLogEnabled
60      implements ArchetypeArtifactManager
61  {
62      /**
63       * @plexus.requirement
64       */
65      private Downloader downloader;
66  
67      /**
68       * @plexus.requirement
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                     // not supposed to be file.separator
354                     String resource = entry.getName().substring( Constants.ARCHETYPE_RESOURCES.length() + 1 );
355                     getLogger().debug( "  - found resource (" + Constants.ARCHETYPE_RESOURCES + "/)" + resource );
356                     // TODO:FIXME
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 }