| package org.apache.maven.archetype.common; |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| import org.apache.commons.io.IOUtils; |
| import org.apache.maven.archetype.downloader.DownloadException; |
| import org.apache.maven.archetype.downloader.DownloadNotFoundException; |
| import org.apache.maven.archetype.downloader.Downloader; |
| import org.apache.maven.archetype.exception.UnknownArchetype; |
| import org.apache.maven.archetype.metadata.ArchetypeDescriptor; |
| import org.apache.maven.archetype.metadata.io.xpp3.ArchetypeDescriptorXpp3Reader; |
| import org.apache.maven.archetype.old.descriptor.ArchetypeDescriptorBuilder; |
| import org.apache.maven.artifact.repository.ArtifactRepository; |
| import org.apache.maven.model.Model; |
| import org.apache.maven.project.ProjectBuildingRequest; |
| import org.codehaus.plexus.component.annotations.Component; |
| import org.codehaus.plexus.component.annotations.Requirement; |
| import org.codehaus.plexus.logging.AbstractLogEnabled; |
| import org.codehaus.plexus.util.ReaderFactory; |
| import org.codehaus.plexus.util.xml.pull.XmlPullParserException; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.Reader; |
| |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| import java.net.URLClassLoader; |
| |
| import java.util.ArrayList; |
| import java.util.Enumeration; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.TreeMap; |
| import java.util.zip.ZipEntry; |
| import java.util.zip.ZipFile; |
| |
| @Component( role = ArchetypeArtifactManager.class ) |
| public class DefaultArchetypeArtifactManager |
| extends AbstractLogEnabled |
| implements ArchetypeArtifactManager |
| { |
| @Requirement |
| private Downloader downloader; |
| |
| @Requirement |
| private PomManager pomManager; |
| |
| private Map<String, File> archetypeCache = new TreeMap<String, File>(); |
| |
| @Override |
| public File getArchetypeFile( final String groupId, final String artifactId, final String version, |
| ArtifactRepository archetypeRepository, final ArtifactRepository localRepository, |
| final List<ArtifactRepository> repositories, ProjectBuildingRequest buildingRequest ) |
| throws UnknownArchetype |
| { |
| try |
| { |
| File archetype = getArchetype( groupId, artifactId, version ); |
| |
| if ( archetype == null ) |
| { |
| archetype = |
| downloader.download( groupId, artifactId, version, archetypeRepository, localRepository, |
| repositories, buildingRequest ); |
| |
| setArchetype( groupId, artifactId, version, archetype ); |
| } |
| return archetype; |
| } |
| catch ( DownloadNotFoundException ex ) |
| { |
| throw new UnknownArchetype( ex ); |
| } |
| catch ( DownloadException ex ) |
| { |
| throw new UnknownArchetype( ex ); |
| } |
| } |
| |
| @Override |
| public ClassLoader getArchetypeJarLoader( File archetypeFile ) |
| throws UnknownArchetype |
| { |
| try |
| { |
| URL[] urls = new URL[1]; |
| |
| urls[0] = archetypeFile.toURI().toURL(); |
| |
| return new URLClassLoader( urls ); |
| } |
| catch ( MalformedURLException e ) |
| { |
| throw new UnknownArchetype( e ); |
| } |
| } |
| |
| @Override |
| public Model getArchetypePom( File jar ) |
| throws XmlPullParserException, UnknownArchetype, IOException |
| { |
| |
| try ( ZipFile zipFile = getArchetypeZipFile( jar ) ) |
| { |
| String pomFileName = null; |
| |
| Enumeration<? extends ZipEntry> enumeration = zipFile.entries(); |
| while ( enumeration.hasMoreElements() ) |
| { |
| ZipEntry el = enumeration.nextElement(); |
| |
| String entry = el.getName(); |
| if ( entry.startsWith( "META-INF" ) && entry.endsWith( "pom.xml" ) ) |
| { |
| pomFileName = entry; |
| } |
| } |
| |
| if ( pomFileName == null ) |
| { |
| return null; |
| } |
| |
| ZipEntry pom = zipFile.getEntry( pomFileName ); |
| |
| if ( pom == null ) |
| { |
| return null; |
| } |
| return pomManager.readPom( zipFile.getInputStream( pom ) ); |
| } |
| } |
| |
| @Override |
| public ZipFile getArchetypeZipFile( File archetypeFile ) |
| throws UnknownArchetype |
| { |
| try |
| { |
| return new ZipFile( archetypeFile ); |
| } |
| catch ( IOException e ) |
| { |
| throw new UnknownArchetype( e ); |
| } |
| } |
| |
| @Override |
| public boolean isFileSetArchetype( File archetypeFile ) |
| { |
| getLogger().debug( "checking fileset archetype status on " + archetypeFile ); |
| |
| try ( ZipFile zipFile = getArchetypeZipFile( archetypeFile ) ) |
| { |
| return isFileSetArchetype( zipFile ); |
| } |
| catch ( IOException | UnknownArchetype e ) |
| { |
| getLogger().debug( e.toString() ); |
| return false; |
| } |
| } |
| |
| @Override |
| public boolean isFileSetArchetype( String groupId, String artifactId, String version, |
| ArtifactRepository archetypeRepository, ArtifactRepository localRepository, |
| List<ArtifactRepository> repositories, ProjectBuildingRequest buildingRequest ) |
| { |
| try |
| { |
| File archetypeFile = getArchetypeFile( groupId, artifactId, version, archetypeRepository, |
| localRepository, repositories, buildingRequest ); |
| |
| return isFileSetArchetype( archetypeFile ); |
| } |
| catch ( UnknownArchetype e ) |
| { |
| getLogger().debug( e.toString() ); |
| return false; |
| } |
| } |
| |
| @Override |
| public boolean isOldArchetype( File archetypeFile ) |
| { |
| getLogger().debug( "checking old archetype status on " + archetypeFile ); |
| |
| try ( ZipFile zipFile = getArchetypeZipFile( archetypeFile ) ) |
| { |
| return isOldArchetype( zipFile ); |
| } |
| catch ( IOException | UnknownArchetype e ) |
| { |
| getLogger().debug( e.toString() ); |
| return false; |
| } |
| } |
| |
| @Override |
| public boolean isOldArchetype( String groupId, String artifactId, String version, |
| ArtifactRepository archetypeRepository, ArtifactRepository localRepository, |
| List<ArtifactRepository> repositories, ProjectBuildingRequest buildingRequest ) |
| { |
| try |
| { |
| File archetypeFile = getArchetypeFile( groupId, artifactId, version, archetypeRepository, |
| localRepository, repositories, buildingRequest ); |
| |
| return isOldArchetype( archetypeFile ); |
| } |
| catch ( UnknownArchetype e ) |
| { |
| getLogger().debug( e.toString() ); |
| return false; |
| } |
| } |
| |
| @Override |
| public boolean exists( String archetypeGroupId, String archetypeArtifactId, String archetypeVersion, |
| ArtifactRepository archetypeRepository, ArtifactRepository localRepository, |
| List<ArtifactRepository> remoteRepositories, ProjectBuildingRequest buildingRequest ) |
| { |
| try |
| { |
| File archetype = getArchetype( archetypeGroupId, archetypeArtifactId, archetypeVersion ); |
| if ( archetype == null ) |
| { |
| archetype = |
| downloader.download( archetypeGroupId, archetypeArtifactId, archetypeVersion, archetypeRepository, |
| localRepository, remoteRepositories, buildingRequest ); |
| setArchetype( archetypeGroupId, archetypeArtifactId, archetypeVersion, archetype ); |
| } |
| |
| return archetype.exists(); |
| } |
| catch ( DownloadException e ) |
| { |
| getLogger().debug( |
| "Archetype " + archetypeGroupId + ":" + archetypeArtifactId + ":" + archetypeVersion |
| + " doesn't exist", e ); |
| return false; |
| } |
| catch ( DownloadNotFoundException e ) |
| { |
| getLogger().debug( |
| "Archetype " + archetypeGroupId + ":" + archetypeArtifactId + ":" + archetypeVersion |
| + " doesn't exist", e ); |
| return false; |
| } |
| } |
| |
| @Override |
| public String getPostGenerationScript( File archetypeFile ) throws UnknownArchetype |
| { |
| try ( ZipFile zipFile = getArchetypeZipFile( archetypeFile ) ) |
| { |
| Reader reader = getDescriptorReader( zipFile, Constants.ARCHETYPE_POST_GENERATION_SCRIPT ); |
| return reader == null ? null : IOUtils.toString( reader ); |
| } |
| catch ( IOException e ) |
| { |
| throw new UnknownArchetype( e ); |
| } |
| } |
| |
| @Override |
| public ArchetypeDescriptor getFileSetArchetypeDescriptor( File archetypeFile ) |
| throws UnknownArchetype |
| { |
| try ( ZipFile zipFile = getArchetypeZipFile( archetypeFile ) ) |
| { |
| return loadFileSetArchetypeDescriptor( zipFile ); |
| } |
| catch ( XmlPullParserException | IOException e ) |
| { |
| throw new UnknownArchetype( e ); |
| } |
| } |
| |
| @Override |
| public org.apache.maven.archetype.metadata.ArchetypeDescriptor getFileSetArchetypeDescriptor( String groupId, |
| String artifactId, |
| String version, |
| ArtifactRepository archetypeRepository, |
| ArtifactRepository localRepository, |
| List<ArtifactRepository> repositories, |
| ProjectBuildingRequest buildingRequest ) |
| throws UnknownArchetype |
| { |
| File archetypeFile = getArchetypeFile( groupId, artifactId, version, archetypeRepository, localRepository, |
| repositories, buildingRequest ); |
| |
| return getFileSetArchetypeDescriptor( archetypeFile ); |
| } |
| |
| @Override |
| public List<String> getFilesetArchetypeResources( File archetypeFile ) |
| throws UnknownArchetype |
| { |
| getLogger().debug( "getFilesetArchetypeResources( \"" + archetypeFile.getAbsolutePath() + "\" )" ); |
| List<String> archetypeResources = new ArrayList<>(); |
| |
| try ( ZipFile zipFile = getArchetypeZipFile( archetypeFile ) ) |
| { |
| Enumeration<? extends ZipEntry> enumeration = zipFile.entries(); |
| while ( enumeration.hasMoreElements() ) |
| { |
| ZipEntry entry = enumeration.nextElement(); |
| |
| if ( entry.getName().startsWith( Constants.ARCHETYPE_RESOURCES ) ) |
| { |
| // not supposed to be file.separator |
| String resource = entry.getName().substring( Constants.ARCHETYPE_RESOURCES.length() + 1 ); |
| getLogger().debug( " - found resource (" + Constants.ARCHETYPE_RESOURCES + "/)" + resource ); |
| // TODO:FIXME |
| archetypeResources.add( resource ); |
| } |
| else |
| { |
| getLogger().debug( " - ignored resource " + entry.getName() ); |
| } |
| } |
| return archetypeResources; |
| } |
| catch ( IOException e ) |
| { |
| throw new UnknownArchetype( e ); |
| } |
| } |
| |
| @Override |
| public org.apache.maven.archetype.old.descriptor.ArchetypeDescriptor getOldArchetypeDescriptor( File archetypeFile ) |
| throws UnknownArchetype |
| { |
| try ( ZipFile zipFile = getArchetypeZipFile( archetypeFile ) ) |
| { |
| return loadOldArchetypeDescriptor( zipFile ); |
| } |
| catch ( XmlPullParserException | IOException e ) |
| { |
| throw new UnknownArchetype( e ); |
| } |
| } |
| |
| @Override |
| public org.apache.maven.archetype.old.descriptor.ArchetypeDescriptor getOldArchetypeDescriptor( String groupId, |
| String artifactId, |
| String version, |
| ArtifactRepository archetypeRepository, |
| ArtifactRepository localRepository, |
| List<ArtifactRepository> repositories, |
| ProjectBuildingRequest buildingRequest ) |
| throws UnknownArchetype |
| { |
| File archetypeFile = getArchetypeFile( groupId, artifactId, version, archetypeRepository, localRepository, |
| repositories, buildingRequest ); |
| |
| return getOldArchetypeDescriptor( archetypeFile ); |
| } |
| |
| private File getArchetype( String archetypeGroupId, String archetypeArtifactId, String archetypeVersion ) |
| { |
| String key = archetypeGroupId + ":" + archetypeArtifactId + ":" + archetypeVersion; |
| |
| if ( archetypeCache.containsKey( key ) ) |
| { |
| getLogger().debug( "Found archetype " + key + " in cache: " + archetypeCache.get( key ) ); |
| |
| return archetypeCache.get( key ); |
| } |
| |
| getLogger().debug( "Not found archetype " + key + " in cache" ); |
| return null; |
| } |
| |
| private void setArchetype( String archetypeGroupId, String archetypeArtifactId, String archetypeVersion, |
| File archetype ) |
| { |
| String key = archetypeGroupId + ":" + archetypeArtifactId + ":" + archetypeVersion; |
| |
| archetypeCache.put( key, archetype ); |
| } |
| |
| private boolean isFileSetArchetype( ZipFile zipFile ) |
| throws IOException |
| { |
| try ( Reader reader = getArchetypeDescriptorReader( zipFile ); ) |
| { |
| return ( reader != null ); |
| } |
| } |
| |
| private boolean isOldArchetype( ZipFile zipFile ) |
| throws IOException |
| { |
| try ( Reader reader = getOldArchetypeDescriptorReader( zipFile ) ) |
| { |
| return ( reader != null ); |
| } |
| } |
| |
| private org.apache.maven.archetype.metadata.ArchetypeDescriptor loadFileSetArchetypeDescriptor( ZipFile zipFile ) |
| throws IOException, XmlPullParserException |
| { |
| |
| try ( Reader reader = getArchetypeDescriptorReader( zipFile ) ) |
| { |
| if ( reader == null ) |
| { |
| return null; |
| } |
| |
| ArchetypeDescriptorXpp3Reader archetypeReader = new ArchetypeDescriptorXpp3Reader(); |
| return archetypeReader.read( reader, false ); |
| } |
| catch ( IOException | XmlPullParserException e ) |
| { |
| throw e; |
| } |
| } |
| |
| private org.apache.maven.archetype.old.descriptor.ArchetypeDescriptor loadOldArchetypeDescriptor( ZipFile zipFile ) |
| throws IOException, XmlPullParserException |
| { |
| try ( Reader reader = getOldArchetypeDescriptorReader( zipFile ) ) |
| { |
| if ( reader == null ) |
| { |
| return null; |
| } |
| |
| ArchetypeDescriptorBuilder builder = new ArchetypeDescriptorBuilder(); |
| return builder.build( reader ); |
| } |
| catch ( IOException | XmlPullParserException ex ) |
| { |
| throw ex; |
| } |
| } |
| |
| private Reader getArchetypeDescriptorReader( ZipFile zipFile ) |
| throws IOException |
| { |
| return getDescriptorReader( zipFile, Constants.ARCHETYPE_DESCRIPTOR ); |
| } |
| |
| private Reader getOldArchetypeDescriptorReader( ZipFile zipFile ) |
| throws IOException |
| { |
| Reader reader = getDescriptorReader( zipFile, Constants.OLD_ARCHETYPE_DESCRIPTOR ); |
| |
| if ( reader == null ) |
| { |
| reader = getDescriptorReader( zipFile, Constants.OLDER_ARCHETYPE_DESCRIPTOR ); |
| } |
| |
| return reader; |
| } |
| |
| private Reader getDescriptorReader( ZipFile zipFile, String descriptor ) |
| throws IOException |
| { |
| ZipEntry entry = searchEntry( zipFile, descriptor ); |
| |
| if ( entry == null ) |
| { |
| return null; |
| } |
| |
| InputStream is = zipFile.getInputStream( entry ); |
| |
| if ( is == null ) |
| { |
| throw new IOException( "The " + descriptor + " descriptor cannot be read in " + zipFile.getName() + "." ); |
| } |
| |
| return ReaderFactory.newReader( is, ReaderFactory.UTF_8 ); |
| } |
| |
| private ZipEntry searchEntry( ZipFile zipFile, String searchString ) |
| { |
| getLogger().debug( "Searching for " + searchString + " inside " + zipFile.getName() ); |
| |
| Enumeration<? extends ZipEntry> enu = zipFile.entries(); |
| while ( enu.hasMoreElements() ) |
| { |
| ZipEntry entryfound = enu.nextElement(); |
| getLogger().debug( " - " + entryfound.getName() ); |
| |
| if ( searchString.equals( entryfound.getName() ) ) |
| { |
| getLogger().debug( "Entry found" ); |
| return entryfound; |
| } |
| } |
| return null; |
| } |
| |
| } |