org.apache.maven.plugin.assembly.archive.DefaultAssemblyArchiver Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of maven-assembly-plugin Show documentation
Show all versions of maven-assembly-plugin Show documentation
A Maven plugin to create archives of your project's sources, classes, dependencies etc. from flexible assembly descriptors.
package org.apache.maven.plugin.assembly.archive;
/*
* 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.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.plugin.DebugConfigurationListener;
import org.apache.maven.plugin.assembly.AssemblerConfigurationSource;
import org.apache.maven.plugin.assembly.AssemblyContext;
import org.apache.maven.plugin.assembly.DefaultAssemblyContext;
import org.apache.maven.plugin.assembly.InvalidAssemblerConfigurationException;
import org.apache.maven.plugin.assembly.archive.archiver.AssemblyProxyArchiver;
import org.apache.maven.plugin.assembly.archive.phase.AssemblyArchiverPhase;
import org.apache.maven.plugin.assembly.artifact.DependencyResolver;
import org.apache.maven.plugin.assembly.filter.ComponentsXmlArchiverFileFilter;
import org.apache.maven.plugin.assembly.filter.ContainerDescriptorHandler;
import org.apache.maven.plugin.assembly.format.AssemblyFormattingException;
import org.apache.maven.plugin.assembly.interpolation.AssemblyExpressionEvaluator;
import org.apache.maven.plugin.assembly.model.Assembly;
import org.apache.maven.plugin.assembly.model.ContainerDescriptorHandlerConfig;
import org.apache.maven.plugin.assembly.utils.AssemblyFileUtils;
import org.apache.maven.plugin.assembly.utils.AssemblyFormatUtils;
import org.apache.maven.project.artifact.InvalidDependencyVersionException;
import org.codehaus.plexus.PlexusConstants;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.archiver.Archiver;
import org.codehaus.plexus.archiver.ArchiverException;
import org.codehaus.plexus.archiver.filters.JarSecurityFileSelector;
import org.codehaus.plexus.archiver.jar.JarArchiver;
import org.codehaus.plexus.archiver.manager.ArchiverManager;
import org.codehaus.plexus.archiver.manager.NoSuchArchiverException;
import org.codehaus.plexus.archiver.tar.TarArchiver;
import org.codehaus.plexus.archiver.tar.TarLongFileMode;
import org.codehaus.plexus.archiver.war.WarArchiver;
import org.codehaus.plexus.collections.ActiveCollectionManager;
import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
import org.codehaus.plexus.component.configurator.ComponentConfigurator;
import org.codehaus.plexus.component.configurator.ConfigurationListener;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.configuration.PlexusConfiguration;
import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
import org.codehaus.plexus.context.Context;
import org.codehaus.plexus.context.ContextException;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Controller component designed to organize the many activities involved in
* creating an assembly archive. This includes locating and configuring {@link Archiver}
* instances, executing multiple {@link AssemblyArchiverPhase} instances to
* interpret the various sections of the assembly descriptor and determine which
* files to add, and other associated activities.
*
* @version $Id: DefaultAssemblyArchiver.java 887709 2009-12-06 16:48:23Z bentmann $
* @plexus.component role="org.apache.maven.plugin.assembly.archive.AssemblyArchiver" role-hint="default"
*/
public class DefaultAssemblyArchiver
extends AbstractLogEnabled
implements AssemblyArchiver, Contextualizable
{
/**
* @plexus.requirement
*/
private ArchiverManager archiverManager;
/**
* @plexus.requirement role="org.apache.maven.plugin.assembly.archive.phase.AssemblyArchiverPhase"
*/
private List assemblyPhases;
/**
* @plexus.requirement role="org.apache.maven.plugin.assembly.filter.ContainerDescriptorHandler"
*/
private Map containerDescriptorHandlers;
/**
* @plexus.requirement
*/
private DependencyResolver dependencyResolver;
private PlexusContainer container;
public DefaultAssemblyArchiver()
{
// needed for plexus
}
// introduced for testing.
protected DefaultAssemblyArchiver( ArchiverManager archiverManager, ActiveCollectionManager collectionManager,
DependencyResolver resolver, List assemblyPhases )
{
this.archiverManager = archiverManager;
dependencyResolver = resolver;
this.assemblyPhases = assemblyPhases;
}
/**
* Create the assembly archive. Generally:
*
*
* - Setup any directory structures for temporary files
* - Calculate the output directory/file for the assembly
* - Setup any handler components for special descriptor files we may encounter
* - Lookup and configure the {@link Archiver} to be used
* - Determine what, if any, dependency resolution will be required, and
* resolve any dependency-version conflicts up front to produce a
* managed-version map for the whole assembly process.
* - Iterate through the available {@link AssemblyArchiverPhase} instances,
* executing each to handle a different top-level section of the
* assembly descriptor, if that section is present.
*
*/
public File createArchive( Assembly assembly, String fullName, String format,
AssemblerConfigurationSource configSource )
throws ArchiveCreationException, AssemblyFormattingException, InvalidAssemblerConfigurationException
{
String filename = fullName;
if ( !configSource.isIgnoreDirFormatExtensions() || !format.startsWith( "dir" ) )
{
filename += "." + format;
}
AssemblyFileUtils.verifyTempDirectoryAvailability( configSource.getTemporaryRootDirectory(), getLogger() );
File outputDirectory = configSource.getOutputDirectory();
File destFile = new File( outputDirectory, filename );
try
{
String finalName = configSource.getFinalName();
String specifiedBasedir = assembly.getBaseDirectory();
String basedir = finalName;
if ( specifiedBasedir != null )
{
basedir = AssemblyFormatUtils.getOutputDirectory( specifiedBasedir, configSource.getProject(),
null, finalName, configSource );
}
List containerHandlers = selectContainerDescriptorHandlers( assembly.getContainerDescriptorHandlers(), configSource );
Archiver archiver = createArchiver( format, assembly.isIncludeBaseDirectory(), basedir, configSource,
containerHandlers );
archiver.setDestFile( destFile );
Map managedVersionMap = dependencyResolver.buildManagedVersionMap( assembly, configSource );
AssemblyContext context = new DefaultAssemblyContext().setManagedVersionMap( managedVersionMap );
for ( Iterator phaseIterator = assemblyPhases.iterator(); phaseIterator.hasNext(); )
{
AssemblyArchiverPhase phase = (AssemblyArchiverPhase) phaseIterator.next();
phase.execute( assembly, archiver, configSource, context );
}
archiver.createArchive();
}
catch ( ArchiverException e )
{
throw new ArchiveCreationException( "Error creating assembly archive " + assembly.getId() + ": " + e.getMessage(), e );
}
catch ( IOException e )
{
throw new ArchiveCreationException( "Error creating assembly archive " + assembly.getId() + ": " + e.getMessage(), e );
}
catch ( NoSuchArchiverException e )
{
throw new ArchiveCreationException( "Unable to obtain archiver for extension '" + format + "'" );
}
catch ( ArtifactResolutionException e )
{
throw new ArchiveCreationException( "Unable to create managed-version map for all assembly activities: " + e.getMessage(), e );
}
catch ( InvalidVersionSpecificationException e )
{
throw new ArchiveCreationException( "Unable to create managed-version map for all assembly activities: " + e.getMessage(), e );
}
catch ( InvalidDependencyVersionException e )
{
throw new ArchiveCreationException( "Unable to create managed-version map for all assembly activities: " + e.getMessage(), e );
}
return destFile;
}
private List selectContainerDescriptorHandlers( List requestedContainerDescriptorHandlers, AssemblerConfigurationSource configSource )
throws InvalidAssemblerConfigurationException
{
getLogger().debug(
"All known ContainerDescritporHandler components: "
+ ( containerDescriptorHandlers == null ? "none; map is null."
: "" + containerDescriptorHandlers.keySet() ) );
if ( requestedContainerDescriptorHandlers == null )
{
requestedContainerDescriptorHandlers = new ArrayList();
}
List handlers = new ArrayList();
boolean foundPlexus = false;
if ( ( requestedContainerDescriptorHandlers != null ) && !requestedContainerDescriptorHandlers.isEmpty() )
{
for ( Iterator it = requestedContainerDescriptorHandlers.iterator(); it.hasNext(); )
{
ContainerDescriptorHandlerConfig config = (ContainerDescriptorHandlerConfig) it.next();
String hint = config.getHandlerName();
ContainerDescriptorHandler handler = (ContainerDescriptorHandler) containerDescriptorHandlers.get( hint );
if ( handler == null )
{
throw new InvalidAssemblerConfigurationException( "Cannot find ContainerDescriptorHandler with hint: " + hint );
}
getLogger().debug( "Found container descriptor handler with hint: " + hint + " (component: " + handler + ")" );
if ( config.getConfiguration() != null )
{
getLogger().debug( "Configuring handler with:\n\n" + config.getConfiguration() + "\n\n" );
configureContainerDescriptorHandler( handler, (Xpp3Dom) config.getConfiguration(), configSource );
}
handlers.add( handler );
if ( "plexus".equals( hint ) )
{
foundPlexus = true;
}
}
}
if ( !foundPlexus )
{
handlers.add( new ComponentsXmlArchiverFileFilter() );
}
return handlers;
}
/**
* Creates the necessary archiver to build the distribution file.
*
* @param format
* Archive format
* @param includeBaseDir
* @param finalName
* @param configSource
* @param containerHandlers
* @return archiver Archiver generated
* @throws org.codehaus.plexus.archiver.ArchiverException
* @throws org.codehaus.plexus.archiver.manager.NoSuchArchiverException
*/
protected Archiver createArchiver( String format, boolean includeBaseDir, String finalName,
AssemblerConfigurationSource configSource,
List containerHandlers )
throws ArchiverException, NoSuchArchiverException
{
Archiver archiver;
if ( format.startsWith( "tar" ) )
{
archiver = createTarArchiver( format, configSource.getTarLongFileMode() );
}
else if ( "war".equals( format ) )
{
archiver = createWarArchiver();
}
else
{
archiver = archiverManager.getArchiver( format );
}
List extraSelectors = null;
List extraFinalizers = null;
if ( archiver instanceof JarArchiver )
{
extraSelectors = Collections.singletonList( new JarSecurityFileSelector() );
extraFinalizers = Collections.singletonList( new ManifestCreationFinalizer( configSource.getProject(),
configSource.getJarArchiveConfiguration() ) );
}
if ( configSource.getArchiverConfig() != null )
{
configureArchiver( archiver, configSource );
}
String prefix = "";
if ( includeBaseDir )
{
prefix = finalName;
}
archiver = new AssemblyProxyArchiver( prefix, archiver, containerHandlers, extraSelectors, extraFinalizers, getLogger(), configSource.isDryRun() );
return archiver;
}
private void configureContainerDescriptorHandler( ContainerDescriptorHandler handler, Xpp3Dom config,
AssemblerConfigurationSource configSource )
throws InvalidAssemblerConfigurationException
{
getLogger().debug( "Configuring handler: '" + handler.getClass().getName() + "' -->" );
try
{
configureComponent( handler, config, configSource );
}
catch ( ComponentConfigurationException e )
{
throw new InvalidAssemblerConfigurationException( "Failed to configure handler: "
+ handler.getClass().getName(), e );
}
catch ( ComponentLookupException e )
{
throw new InvalidAssemblerConfigurationException( "Failed to lookup configurator for setup of handler: "
+ handler.getClass().getName(), e );
}
getLogger().debug( "-- end configuration --" );
}
private void configureArchiver( Archiver archiver, AssemblerConfigurationSource configSource )
throws ArchiverException
{
Xpp3Dom config;
try
{
config = Xpp3DomBuilder.build( new StringReader( configSource.getArchiverConfig() ) );
}
catch ( XmlPullParserException e )
{
throw new ArchiverException( "Failed to parse archiver configuration for: " + archiver.getClass().getName(), e );
}
catch ( IOException e )
{
throw new ArchiverException( "Failed to parse archiver configuration for: " + archiver.getClass().getName(), e );
}
getLogger().debug( "Configuring archiver: '" + archiver.getClass().getName() + "' -->" );
try
{
configureComponent( archiver, config, configSource );
}
catch ( ComponentConfigurationException e )
{
throw new ArchiverException( "Failed to configure archiver: " + archiver.getClass().getName(), e );
}
catch ( ComponentLookupException e )
{
throw new ArchiverException( "Failed to lookup configurator for setup of archiver: "
+ archiver.getClass().getName(), e );
}
getLogger().debug( "-- end configuration --" );
}
private void configureComponent( Object component, Xpp3Dom config, AssemblerConfigurationSource configSource )
throws ComponentLookupException, ComponentConfigurationException
{
ComponentConfigurator configurator =
(ComponentConfigurator) container.lookup( ComponentConfigurator.ROLE, "basic" );
ConfigurationListener listener = new DebugConfigurationListener( getLogger() );
ExpressionEvaluator expressionEvaluator = new AssemblyExpressionEvaluator( configSource );
XmlPlexusConfiguration configuration = new XmlPlexusConfiguration( config );
Object[] containerRealm = getContainerRealm();
/*
* NOTE: The signature of configureComponent() has changed in Maven 3.x, the reflection prevents a linkage error
* and makes the code work with both Maven 2 and 3.
*/
try
{
Method configureComponent =
ComponentConfigurator.class.getMethod( "configureComponent", new Class[] { Object.class,
PlexusConfiguration.class, ExpressionEvaluator.class, (Class) containerRealm[1],
ConfigurationListener.class } );
configureComponent.invoke( configurator, new Object[] { component, configuration, expressionEvaluator,
containerRealm[0], listener } );
}
catch ( NoSuchMethodException e )
{
throw new RuntimeException( e );
}
catch ( IllegalAccessException e )
{
throw new RuntimeException( e );
}
catch ( InvocationTargetException e )
{
if ( e.getCause() instanceof ComponentConfigurationException )
{
throw (ComponentConfigurationException) e.getCause();
}
throw new RuntimeException( e.getCause() );
}
}
private Object[] getContainerRealm()
{
/*
* NOTE: The return type of getContainerRealm() has changed in Maven 3.x, the reflection prevents a linkage
* error and makes the code work with both Maven 2 and 3.
*/
try
{
Method getContainerRealm = container.getClass().getMethod( "getContainerRealm", null );
return new Object[] { getContainerRealm.invoke( container, null ), getContainerRealm.getReturnType() };
}
catch ( NoSuchMethodException e )
{
throw new RuntimeException( e );
}
catch ( IllegalAccessException e )
{
throw new RuntimeException( e );
}
catch ( InvocationTargetException e )
{
throw new RuntimeException( e.getCause() );
}
}
protected Archiver createWarArchiver()
throws NoSuchArchiverException
{
WarArchiver warArchiver = (WarArchiver) archiverManager.getArchiver( "war" );
warArchiver.setIgnoreWebxml( false ); // See MNG-1274
return warArchiver;
}
protected Archiver createTarArchiver( String format, String tarLongFileMode )
throws NoSuchArchiverException, ArchiverException
{
TarArchiver tarArchiver = (TarArchiver) archiverManager.getArchiver( "tar" );
int index = format.indexOf( '.' );
if ( index >= 0 )
{
// TODO: this needs a cleanup in plexus archiver - use a real
// typesafe enum
TarArchiver.TarCompressionMethod tarCompressionMethod = new TarArchiver.TarCompressionMethod();
// TODO: this should accept gz and bz2 as well so we can skip
// over the switch
String compression = format.substring( index + 1 );
if ( "gz".equals( compression ) )
{
tarCompressionMethod.setValue( "gzip" );
}
else if ( "bz2".equals( compression ) )
{
tarCompressionMethod.setValue( "bzip2" );
}
else
{
// TODO: better handling
throw new IllegalArgumentException( "Unknown compression format: " + compression );
}
tarArchiver.setCompression( tarCompressionMethod );
}
TarLongFileMode tarFileMode = new TarLongFileMode();
tarFileMode.setValue( tarLongFileMode );
tarArchiver.setLongfile( tarFileMode );
return tarArchiver;
}
public void contextualize( Context context )
throws ContextException
{
container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
}
protected void setContainer( PlexusContainer container )
{
this.container = container;
}
}