All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.maven.plugin.assembly.archive.DefaultAssemblyArchiver Maven / Gradle / Ivy

Go to download

A Maven plugin to create archives of your project's sources, classes, dependencies etc. from flexible assembly descriptors.

There is a newer version: 3.7.1
Show newest version
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:
     * 
     * 
    *
  1. Setup any directory structures for temporary files
  2. *
  3. Calculate the output directory/file for the assembly
  4. *
  5. Setup any handler components for special descriptor files we may encounter
  6. *
  7. Lookup and configure the {@link Archiver} to be used
  8. *
  9. 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.
  10. *
  11. 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.
  12. *
*/ 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; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy