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

org.apache.maven.plugins.assembly.mojos.AbstractAssemblyMojo 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.plugins.assembly.mojos;

/*
 * 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 java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import org.apache.maven.archiver.MavenArchiveConfiguration;
import org.apache.maven.archiver.MavenArchiver;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.assembly.AssemblerConfigurationSource;
import org.apache.maven.plugins.assembly.InvalidAssemblerConfigurationException;
import org.apache.maven.plugins.assembly.archive.ArchiveCreationException;
import org.apache.maven.plugins.assembly.archive.AssemblyArchiver;
import org.apache.maven.plugins.assembly.format.AssemblyFormattingException;
import org.apache.maven.plugins.assembly.io.AssemblyReadException;
import org.apache.maven.plugins.assembly.io.AssemblyReader;
import org.apache.maven.plugins.assembly.model.Assembly;
import org.apache.maven.plugins.assembly.utils.AssemblyFormatUtils;
import org.apache.maven.plugins.assembly.utils.InterpolationConstants;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectHelper;
import org.apache.maven.shared.filtering.MavenReaderFilter;
import org.codehaus.plexus.configuration.PlexusConfiguration;
import org.codehaus.plexus.interpolation.fixed.FixedStringSearchInterpolator;
import org.codehaus.plexus.interpolation.fixed.PrefixedPropertiesValueSource;
import org.codehaus.plexus.interpolation.fixed.PropertiesBasedValueSource;
import org.codehaus.plexus.util.cli.CommandLineUtils;

/**
 * @author Brett Porter
 * @author Vincent Siveton
 */
public abstract class AbstractAssemblyMojo extends AbstractMojo implements AssemblerConfigurationSource
{

    protected FixedStringSearchInterpolator commandLinePropertiesInterpolator;

    protected FixedStringSearchInterpolator envInterpolator;

    protected FixedStringSearchInterpolator mainProjectInterpolator;

    protected FixedStringSearchInterpolator rootInterpolator;

    /**
     * Set to false to exclude the assembly id from the assembly final name, and to create the resultant assembly
     * artifacts without classifier. As such, an assembly artifact having the same format as the packaging of the
     * current Maven project will replace the file for this main project artifact.
     */
    @Parameter( property = "assembly.appendAssemblyId", defaultValue = "true" )
    boolean appendAssemblyId;

    /**
     * The character encoding scheme to be applied when filtering resources.
     */
    @Parameter( property = "encoding", defaultValue = "${project.build.sourceEncoding}" )
    private String encoding;

    /**
     * Expressions preceded with this String won't be interpolated. If you use "\" as the escape string then \${foo}
     * will be replaced with ${foo}.
     *
     * @since 2.4
     */
    @Parameter( property = "assembly.escapeString" )
    private String escapeString;

    /**
     * Flag allowing one or more executions of the assembly plugin to be configured as skipped for a particular build.
     * This makes the assembly plugin more controllable from profiles.
     */
    @Parameter( property = "assembly.skipAssembly", defaultValue = "false" )
    private boolean skipAssembly;

    /**
     * If this flag is set, everything up to the call to Archiver.createArchive() will be executed.
     */
    @Parameter( property = "assembly.dryRun", defaultValue = "false" )
    private boolean dryRun;

    /**
     * If this flag is set, the ".dir" suffix will be suppressed in the output directory name when using assembly/format
     * == 'dir' and other formats that begin with 'dir'. 
* NOTE: Since 2.2-beta-3, the default-value for this is true, NOT false as it used to be. */ @Parameter( defaultValue = "true" ) private boolean ignoreDirFormatExtensions; /** * Local Maven repository where artifacts are cached during the build process. */ @Parameter( defaultValue = "${localRepository}", required = true, readonly = true ) private ArtifactRepository localRepository; /** * */ @Parameter( defaultValue = "${project.remoteArtifactRepositories}", required = true, readonly = true ) private List remoteRepositories; /** * Contains the full list of projects in the reactor. */ @Parameter( defaultValue = "${reactorProjects}", required = true, readonly = true ) private List reactorProjects; /** * The output directory of the assembled distribution file. */ @Parameter( defaultValue = "${project.build.directory}", required = true ) private File outputDirectory; /** * The filename of the assembled distribution file. */ @Parameter( defaultValue = "${project.build.finalName}", required = true, readonly = true ) private String finalName; /** * Directory to unpack JARs into if needed */ @Parameter( defaultValue = "${project.build.directory}/assembly/work", required = true ) private File workDirectory; /** * Specifies the formats of the assembly. Multiple formats can be supplied and the Assembly Plugin will generate an * archive for each desired formats. When deploying your project, all file formats specified will also be deployed. * A format is specified by supplying one of the following values in a <format> subelement: *
    *
  • dir - Creates a directory
  • *
  • zip - Creates a ZIP file format
  • *
  • tar - Creates a TAR format
  • *
  • tar.gz or tgz - Creates a gzip'd TAR format
  • *
  • tar.bz2 or tbz2 - Creates a bzip'd TAR format
  • *
  • tar.snappy - Creates a snappy'd TAR format
  • *
  • tar.xz or txz - Creates a xz'd TAR format
  • *
*/ @Parameter private List formats; /** * A list of descriptor files to generate from. */ @Parameter private String[] descriptors; /** * A list of references to assembly descriptors available on the plugin's classpath. The default classpath includes * these built-in descriptors: bin, jar-with-dependencies, src, and * project. You can add others by adding dependencies * to the plugin. */ @Parameter private String[] descriptorRefs; /** * Directory to scan for descriptor files in. NOTE: This may not work correctly with assembly components. */ @Parameter private File descriptorSourceDirectory; /** * This is the base directory from which archive files are created. This base directory pre-pended to any * <directory> specifications in the assembly descriptor. This is an optional parameter. */ @Parameter private File archiveBaseDirectory; /** * Sets the TarArchiver behavior on file paths with more than 100 characters length. Valid values are: "warn" * (default), "fail", "truncate", "gnu", "posix", "posix_warn" or "omit". */ @Parameter( property = "assembly.tarLongFileMode", defaultValue = "warn" ) private String tarLongFileMode; /** * Base directory of the project. */ @Parameter( defaultValue = "${project.basedir}", required = true, readonly = true ) private File basedir; /** * Maven ProjectHelper. */ @Component private MavenProjectHelper projectHelper; /** * Maven shared filtering utility. */ @Component private MavenReaderFilter mavenReaderFilter; /** * The Maven Session Object */ @Parameter( defaultValue = "${session}", readonly = true, required = true ) private MavenSession mavenSession; /** * Temporary directory that contain the files to be assembled. */ @Parameter( defaultValue = "${project.build.directory}/archive-tmp", required = true, readonly = true ) private File tempRoot; /** * Directory for site generated. */ @Parameter( defaultValue = "${project.reporting.outputDirectory}", readonly = true ) private File siteDirectory; /** * Set to true in order to not fail when a descriptor is missing. */ @Parameter( property = "assembly.ignoreMissingDescriptor", defaultValue = "false" ) private boolean ignoreMissingDescriptor; /** * This is a set of instructions to the archive builder, especially for building .jar files. It enables you to * specify a Manifest file for the jar, in addition to other options. See * Maven Archiver Reference. */ @Parameter private MavenArchiveConfiguration archive; /** * The list of extra filter properties files to be used along with System properties, project properties, and filter * properties files specified in the POM build/filters section, which should be used for the filtering during the * current mojo execution.
Normally, these will be configured from a plugin's execution section, to provide a * different set of filters for a particular execution. */ @Parameter private List filters; /** * A set of additional properties to use for filtering * * @since 3.3.0 */ @Parameter private Properties additionalProperties; /** * If True (default) then the ${project.build.filters} are also used in addition to any further filters defined for * the Assembly. * * @since 2.4.2 */ @Parameter( property = "assembly.includeProjectBuildFilters", defaultValue = "true" ) private boolean includeProjectBuildFilters; /** * Controls whether the assembly plugin tries to attach the resulting assembly to the project. * * @since 2.2-beta-1 */ @Parameter( property = "assembly.attach", defaultValue = "true" ) private boolean attach; /** * Indicates if zip archives (jar,zip etc) being added to the assembly should be compressed again. Compressing again * can result in smaller archive size, but gives noticeably longer execution time. * * @since 2.4 */ @Parameter( defaultValue = "true" ) private boolean recompressZippedFiles; /** * sets the merge manifest mode in the JarArchiver * * @since 3 */ @Parameter private String mergeManifestMode; /** * */ @Component private AssemblyArchiver assemblyArchiver; /** * */ @Component private AssemblyReader assemblyReader; /** * Allows additional configuration options that are specific to a particular type of archive format. This is * intended to capture an XML configuration that will be used to reflectively setup the options on the archiver * instance.
To see the possible options for archiver configuration visit the * * Plexus Archiver Documentation
For instance, to direct an assembly with the "ear" format to use a * particular deployment descriptor, you should specify the following for the archiverConfig value in your plugin * configuration:
*

*

*

     * <appxml>${project.basedir}/somepath/app.xml</appxml>
     * 
*

* * @since 2.2-beta-3 */ @Parameter private PlexusConfiguration archiverConfig; /** * This will cause the assembly to run only at the top of a given module tree. That is, run in the project contained * in the same folder where the mvn execution was launched. * * @since 2.2-beta-4 */ @Parameter( property = "assembly.runOnlyAtExecutionRoot", defaultValue = "false" ) private boolean runOnlyAtExecutionRoot; /** * This will cause the assembly to only update an existing archive, if it exists. *

* Note: The property that can be used on the command line was misspelled as "assembly.updatOnly" * in versions prior to version 2.4. *

* * @since 2.2 */ @Parameter( property = "assembly.updateOnly", defaultValue = "false" ) private boolean updateOnly; /** * @since 2.2 * @deprecated Not used anymore and will be removed in future version */ @Parameter( property = "assembly.useJvmChmod", defaultValue = "false" ) private boolean useJvmChmod; /** *

* Set to true in order to avoid all chmod calls. *

*

*

* NOTE: This will cause the assembly plugin to DISREGARD all fileMode/directoryMode settings in the * assembly descriptor, and all file permissions in unpacked dependencies! *

* * @since 2.2 */ @Parameter( property = "assembly.ignorePermissions", defaultValue = "false" ) private boolean ignorePermissions; /** *

* Set of delimiters for expressions to filter within the resources. These delimiters are specified in the form * 'beginToken*endToken'. If no '*' is given, the delimiter is assumed to be the same for start and end. *

*

* So, the default filtering delimiters might be specified as: *

*

*

     * <delimiters>
     *   <delimiter>${*}</delimiter>
     *   <delimiter>@</delimiter>
     * </delimiters>
     * 
*

* Since the '@' delimiter is the same on both ends, we don't need to specify '@*@' (though we can). *

* * @since 2.4 */ @Parameter private List delimiters; /** * Timestamp for reproducible output archive entries, either formatted as ISO 8601 * yyyy-MM-dd'T'HH:mm:ssXXX or as an int representing seconds since the epoch (like * SOURCE_DATE_EPOCH). * * @since 3.2.0 */ @Parameter( defaultValue = "${project.build.outputTimestamp}" ) private String outputTimestamp; /** * Override of user ID in archive type which can store it. */ @Parameter private Integer overrideUid; /** * Override of user name in archive type which can store it. */ @Parameter private String overrideUserName; /** * Override of group ID in archive type which can store it. */ @Parameter private Integer overrideGid; /** * Override of group name in archive type which can store it. */ @Parameter private String overrideGroupName; public static FixedStringSearchInterpolator mainProjectInterpolator( MavenProject mainProject ) { if ( mainProject != null ) { // 5 return FixedStringSearchInterpolator.create( new org.codehaus.plexus.interpolation.fixed.PrefixedObjectValueSource( InterpolationConstants.PROJECT_PREFIXES, mainProject, true ), // 6 new org.codehaus.plexus.interpolation.fixed.PrefixedPropertiesValueSource( InterpolationConstants.PROJECT_PROPERTIES_PREFIXES, mainProject.getProperties(), true ) ); } else { return FixedStringSearchInterpolator.empty(); } } /** * Create the binary distribution. */ @Override public void execute() throws MojoExecutionException, MojoFailureException { if ( skipAssembly ) { getLog().info( "Assemblies have been skipped per configuration of the skipAssembly parameter." ); return; } // run only at the execution root. if ( runOnlyAtExecutionRoot && !isThisTheExecutionRoot() ) { getLog().info( "Skipping the assembly in this project because it's not the Execution Root" ); return; } List assemblies; try { assemblies = assemblyReader.readAssemblies( this ); } catch ( final AssemblyReadException e ) { throw new MojoExecutionException( "Error reading assemblies: " + e.getMessage(), e ); } catch ( final InvalidAssemblerConfigurationException e ) { throw new MojoFailureException( assemblyReader, e.getMessage(), "Mojo configuration is invalid: " + e.getMessage() ); } // TODO: include dependencies marked for distribution under certain formats // TODO: how, might we plug this into an installer, such as NSIS? MavenArchiver mavenArchiver = new MavenArchiver(); Date outputDate = mavenArchiver.parseOutputTimestamp( outputTimestamp ); boolean warnedAboutMainProjectArtifact = false; for ( final Assembly assembly : assemblies ) { try { final String fullName = AssemblyFormatUtils.getDistributionName( assembly, this ); List effectiveFormats = formats; if ( effectiveFormats == null || effectiveFormats.size() == 0 ) { effectiveFormats = assembly.getFormats(); } if ( effectiveFormats == null || effectiveFormats.size() == 0 ) { throw new MojoFailureException( "No formats specified in the execution parameters or the assembly descriptor." ); } for ( final String format : effectiveFormats ) { final File destFile = assemblyArchiver.createArchive( assembly, fullName, format, this, isRecompressZippedFiles(), getMergeManifestMode(), outputDate ); final MavenProject project = getProject(); final String type = project.getArtifact().getType(); if ( attach && destFile.isFile() ) { if ( isAssemblyIdAppended() ) { projectHelper.attachArtifact( project, format, assembly.getId(), destFile ); } else if ( !"pom".equals( type ) && format.equals( type ) ) { if ( !warnedAboutMainProjectArtifact ) { final StringBuilder message = new StringBuilder(); message.append( "Configuration option 'appendAssemblyId' is set to false." ); message.append( "\nInstead of attaching the assembly file: " ).append( destFile ); message.append( ", it will become the file for main project artifact." ); message.append( "\nNOTE: If multiple descriptors or descriptor-formats are provided " + "for this project, the value of this file will be " + "non-deterministic!" ); getLog().warn( message ); warnedAboutMainProjectArtifact = true; } final File existingFile = project.getArtifact().getFile(); if ( ( existingFile != null ) && existingFile.exists() ) { getLog().warn( "Replacing pre-existing project main-artifact file: " + existingFile + "\nwith assembly file: " + destFile ); } project.getArtifact().setFile( destFile ); } else { projectHelper.attachArtifact( project, format, null, destFile ); } } else if ( attach ) { getLog().warn( "Assembly file: " + destFile + " is not a regular file (it may be a directory). " + "It cannot be attached to the project build for installation or " + "deployment." ); } } } catch ( final ArchiveCreationException | AssemblyFormattingException e ) { throw new MojoExecutionException( "Failed to create assembly: " + e.getMessage(), e ); } catch ( final InvalidAssemblerConfigurationException e ) { throw new MojoFailureException( assembly, "Assembly is incorrectly configured: " + assembly.getId(), "Assembly: " + assembly.getId() + " is not configured correctly: " + e.getMessage() ); } } } private FixedStringSearchInterpolator createRepositoryInterpolator() { final Properties settingsProperties = new Properties(); final MavenSession session = getMavenSession(); if ( getLocalRepository() != null ) { settingsProperties.setProperty( "localRepository", getLocalRepository().getBasedir() ); settingsProperties.setProperty( "settings.localRepository", getLocalRepository().getBasedir() ); } else if ( session != null && session.getSettings() != null ) { settingsProperties.setProperty( "localRepository", session.getSettings().getLocalRepository() ); settingsProperties.setProperty( "settings.localRepository", getLocalRepository().getBasedir() ); } return FixedStringSearchInterpolator.create( new PropertiesBasedValueSource( settingsProperties ) ); } private FixedStringSearchInterpolator createCommandLinePropertiesInterpolator() { Properties commandLineProperties = System.getProperties(); final MavenSession session = getMavenSession(); if ( session != null ) { commandLineProperties = new Properties(); commandLineProperties.putAll( session.getSystemProperties() ); commandLineProperties.putAll( session.getUserProperties() ); } PropertiesBasedValueSource cliProps = new PropertiesBasedValueSource( commandLineProperties ); return FixedStringSearchInterpolator.create( cliProps ); } private FixedStringSearchInterpolator createEnvInterpolator() { try { PrefixedPropertiesValueSource envProps = new PrefixedPropertiesValueSource( Collections.singletonList( "env." ), CommandLineUtils.getSystemEnvVars( false ), true ); return FixedStringSearchInterpolator.create( envProps ); } catch ( IOException e ) { throw new UncheckedIOException( e ); } } /** * Returns true if the current project is located at the Execution Root Directory (where mvn was launched) * * @return if this is the execution root */ boolean isThisTheExecutionRoot() { final Log log = getLog(); log.debug( "Root Folder:" + mavenSession.getExecutionRootDirectory() ); log.debug( "Current Folder:" + basedir ); final boolean result = mavenSession.getExecutionRootDirectory().equalsIgnoreCase( basedir.toString() ); if ( result ) { log.debug( "This is the execution root." ); } else { log.debug( "This is NOT the execution root." ); } return result; } @Override public File getBasedir() { return basedir; } public void setBasedir( final File basedir ) { this.basedir = basedir; } @Override public String[] getDescriptorReferences() { return descriptorRefs; } @Override public File getDescriptorSourceDirectory() { return descriptorSourceDirectory; } @Override public String[] getDescriptors() { return descriptors; } public void setDescriptors( final String[] descriptors ) { this.descriptors = descriptors; } @Override public abstract MavenProject getProject(); @Override public File getSiteDirectory() { return siteDirectory; } public void setSiteDirectory( final File siteDirectory ) { this.siteDirectory = siteDirectory; } @Override public String getFinalName() { return finalName; } public void setFinalName( final String finalName ) { this.finalName = finalName; } @Override public boolean isAssemblyIdAppended() { return appendAssemblyId; } @Override public String getTarLongFileMode() { return tarLongFileMode; } public void setTarLongFileMode( final String tarLongFileMode ) { this.tarLongFileMode = tarLongFileMode; } @Override public File getOutputDirectory() { return outputDirectory; } public void setOutputDirectory( final File outputDirectory ) { this.outputDirectory = outputDirectory; } @Override public MavenArchiveConfiguration getJarArchiveConfiguration() { return archive; } @Override public File getWorkingDirectory() { return workDirectory; } @Override public ArtifactRepository getLocalRepository() { return localRepository; } public void setLocalRepository( final ArtifactRepository localRepository ) { this.localRepository = localRepository; } @Override public File getTemporaryRootDirectory() { return tempRoot; } @Override public File getArchiveBaseDirectory() { return archiveBaseDirectory; } @Override public List getFilters() { if ( filters == null ) { filters = getProject().getBuild().getFilters(); if ( filters == null ) { filters = Collections.emptyList(); } } return filters; } public void setFilters( final List filters ) { this.filters = filters; } public Properties getAdditionalProperties() { return additionalProperties; } @Override public boolean isIncludeProjectBuildFilters() { return includeProjectBuildFilters; } @Override public List getReactorProjects() { return reactorProjects; } public void setReactorProjects( final List reactorProjects ) { this.reactorProjects = reactorProjects; } public void setAppendAssemblyId( final boolean appendAssemblyId ) { this.appendAssemblyId = appendAssemblyId; } public void setArchive( final MavenArchiveConfiguration archive ) { this.archive = archive; } public void setDescriptorRefs( final String[] descriptorRefs ) { this.descriptorRefs = descriptorRefs; } public void setTempRoot( final File tempRoot ) { this.tempRoot = tempRoot; } public void setWorkDirectory( final File workDirectory ) { this.workDirectory = workDirectory; } @Override public List getRemoteRepositories() { return remoteRepositories; } @Override public boolean isDryRun() { return dryRun; } @Override public boolean isIgnoreDirFormatExtensions() { return ignoreDirFormatExtensions; } @Override public boolean isIgnoreMissingDescriptor() { return ignoreMissingDescriptor; } @Override public MavenSession getMavenSession() { return mavenSession; } @Override public String getArchiverConfig() { return archiverConfig == null ? null : archiverConfig.toString(); } @Override public MavenReaderFilter getMavenReaderFilter() { return mavenReaderFilter; } @Override public boolean isUpdateOnly() { return updateOnly; } @Override @Deprecated public boolean isUseJvmChmod() { return useJvmChmod; } @Override public boolean isIgnorePermissions() { return ignorePermissions; } @Override public String getEncoding() { return encoding; } boolean isRecompressZippedFiles() { return recompressZippedFiles; } public String getMergeManifestMode() { return mergeManifestMode; } @Override public String getEscapeString() { return escapeString; } @Override public List getDelimiters() { return delimiters; } public void setDelimiters( List delimiters ) { this.delimiters = delimiters; } @Override public synchronized FixedStringSearchInterpolator getCommandLinePropsInterpolator() { if ( commandLinePropertiesInterpolator == null ) { this.commandLinePropertiesInterpolator = createCommandLinePropertiesInterpolator(); } return commandLinePropertiesInterpolator; } @Override public synchronized FixedStringSearchInterpolator getEnvInterpolator() { if ( envInterpolator == null ) { this.envInterpolator = createEnvInterpolator(); } return envInterpolator; } @Override public synchronized FixedStringSearchInterpolator getRepositoryInterpolator() { if ( rootInterpolator == null ) { this.rootInterpolator = createRepositoryInterpolator(); } return rootInterpolator; } @Override public synchronized FixedStringSearchInterpolator getMainProjectInterpolator() { if ( mainProjectInterpolator == null ) { this.mainProjectInterpolator = mainProjectInterpolator( getProject() ); } return mainProjectInterpolator; } @Override public Integer getOverrideUid() { return this.overrideUid; } @Override public String getOverrideUserName() { return this.overrideUserName; } @Override public Integer getOverrideGid() { return this.overrideGid; } @Override public String getOverrideGroupName() { return this.overrideGroupName; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy