blob: fe9f7daec02f3b0add7bef5fe78d54f75db761f8 [file] [log] [blame]
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<>();
@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;
}
}