org.apache.maven.plugins.resources.ResourcesMojo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of maven-resources-plugin Show documentation
Show all versions of maven-resources-plugin Show documentation
The Resources Plugin handles the copying of project resources to the output
directory. There are two different kinds of resources: main resources and test resources. The
difference is that the main resources are the resources associated with the main
source code while the test resources are associated with the test source code.
Thus, this allows the separation of resources for the main source code and its
unit tests.
package org.apache.maven.plugins.resources;
/*
* 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.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Properties;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Resource;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.filtering.MavenFilteringException;
import org.apache.maven.shared.filtering.MavenResourcesExecution;
import org.apache.maven.shared.filtering.MavenResourcesFiltering;
import org.codehaus.plexus.PlexusConstants;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.context.Context;
import org.codehaus.plexus.context.ContextException;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.StringUtils;
/**
* Copy resources for the main source code to the main output directory. Always uses the project.build.resources element
* to specify the resources to copy.
*
* @author Michal Maczka
* @author Jason van Zyl
* @author Andreas Hoheneder
* @author William Ferguson
*/
@Mojo( name = "resources", defaultPhase = LifecyclePhase.PROCESS_RESOURCES, requiresProject = true, threadSafe = true )
public class ResourcesMojo
extends AbstractMojo
implements Contextualizable
{
/**
* The character encoding scheme to be applied when filtering resources.
*/
@Parameter( defaultValue = "${project.build.sourceEncoding}" )
protected String encoding;
/**
* The output directory into which to copy the resources.
*/
@Parameter( defaultValue = "${project.build.outputDirectory}", required = true )
private File outputDirectory;
/**
* The list of resources we want to transfer.
*/
@Parameter( defaultValue = "${project.resources}", required = true, readonly = true )
private List resources;
/**
*
*/
@Parameter( defaultValue = "${project}", readonly = true, required = true )
protected MavenProject project;
/**
* The list of additional filter properties files to be used along with System and project properties, which would
* be used for the filtering.
* See also: {@link ResourcesMojo#filters}.
*
* @since 2.4
*/
@Parameter( defaultValue = "${project.build.filters}", readonly = true )
protected List buildFilters;
/**
* 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. For instance, starting in Maven 2.2.0, you have the option of configuring executions with
* the id's default-resources
and default-testResources
to supply different configurations
* for the two different types of resources. By supplying extraFilters
configurations, you can separate
* which filters are used for which type of resource.
*/
@Parameter
protected List filters;
/**
* If false, don't use the filters specified in the build/filters section of the POM when processing resources in
* this mojo execution.
* See also: {@link ResourcesMojo#buildFilters} and {@link ResourcesMojo#filters}
*
* @since 2.4
*/
@Parameter( defaultValue = "true" )
protected boolean useBuildFilters;
/**
*
*/
@Component( role = MavenResourcesFiltering.class, hint = "default" )
protected MavenResourcesFiltering mavenResourcesFiltering;
/**
*
*/
@Parameter( defaultValue = "${session}", readonly = true, required = true )
protected MavenSession session;
/**
* Expressions preceded with this string won't be interpolated. Anything else preceded with this string will be
* passed through unchanged. For example {@code \${foo}} will be replaced with {@code ${foo}} but {@code \\${foo}}
* will be replaced with {@code \\value of foo}, if this parameter has been set to the backslash.
*
* @since 2.3
*/
@Parameter
protected String escapeString;
/**
* Overwrite existing files even if the destination files are newer.
*
* @since 2.3
*/
@Parameter( defaultValue = "false" )
private boolean overwrite;
/**
* Copy any empty directories included in the Resources.
*
* @since 2.3
*/
@Parameter( defaultValue = "false" )
protected boolean includeEmptyDirs;
/**
* Additional file extensions to not apply filtering (already defined are : jpg, jpeg, gif, bmp, png)
*
* @since 2.3
*/
@Parameter
protected List nonFilteredFileExtensions;
/**
* Whether to escape backslashes and colons in windows-style paths.
*
* @since 2.4
*/
@Parameter( defaultValue = "true" )
protected boolean escapeWindowsPaths;
/**
*
* Set of delimiters for expressions to filter within the resources. These delimiters are specified in the form
* {@code beginToken*endToken}. If no {@code *} 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 {@code @} delimiter is the same on both ends, we don't need to specify {@code @*@} (though we can).
*
*
* @since 2.4
*/
@Parameter
protected LinkedHashSet delimiters;
/**
* Use default delimiters in addition to custom delimiters, if any.
*
* @since 2.4
*/
@Parameter( defaultValue = "true" )
protected boolean useDefaultDelimiters;
/**
* By default files like {@code .gitignore}, {@code .cvsignore} etc. are excluded which means they will not being
* copied. If you need them for a particular reason you can do that by settings this to {@code false}. This means
* all files like the following will be copied.
*
* - Misc: **/*~, **/#*#, **/.#*, **/%*%, **/._*
* - CVS: **/CVS, **/CVS/**, **/.cvsignore
* - RCS: **/RCS, **/RCS/**
* - SCCS: **/SCCS, **/SCCS/**
* - VSSercer: **/vssver.scc
* - MKS: **/project.pj
* - SVN: **/.svn, **/.svn/**
* - GNU: **/.arch-ids, **/.arch-ids/**
* - Bazaar: **/.bzr, **/.bzr/**
* - SurroundSCM: **/.MySCMServerInfo
* - Mac: **/.DS_Store
* - Serena Dimension: **/.metadata, **/.metadata/**
* - Mercurial: **/.hg, **/.hg/**
* - GIT: **/.git, **/.gitignore, **/.gitattributes, **/.git/**
* - Bitkeeper: **/BitKeeper, **/BitKeeper/**, **/ChangeSet,
* **/ChangeSet/**
* - Darcs: **/_darcs, **/_darcs/**, **/.darcsrepo,
* **/.darcsrepo/****/-darcs-backup*, **/.darcs-temp-mail
*
*
* @since 3.0.0
*/
@Parameter( defaultValue = "true" )
protected boolean addDefaultExcludes;
/**
*
* List of plexus components hint which implements
* {@link MavenResourcesFiltering#filterResources(MavenResourcesExecution)}. They will be executed after the
* resources copying/filtering.
*
*
* @since 2.4
*/
@Parameter
private List mavenFilteringHints;
/**
* @since 2.4
*/
private PlexusContainer plexusContainer;
/**
* @since 2.4
*/
private List mavenFilteringComponents = new ArrayList();
/**
* stop searching endToken at the end of line
*
* @since 2.5
*/
@Parameter( defaultValue = "false" )
private boolean supportMultiLineFiltering;
/**
* Support filtering of filenames folders etc.
*
* @since 3.0.0
*/
@Parameter( defaultValue = "false" )
private boolean fileNameFiltering;
/**
* You can skip the execution of the plugin if you need to. Its use is NOT RECOMMENDED, but quite convenient on
* occasion.
*
* @since 3.0.0
*/
@Parameter( property = "maven.resources.skip", defaultValue = "false" )
private boolean skip;
/** {@inheritDoc} */
public void contextualize( Context context )
throws ContextException
{
plexusContainer = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
}
/** {@inheritDoc} */
public void execute()
throws MojoExecutionException
{
if ( isSkip() )
{
getLog().info( "Skipping the execution." );
return;
}
if ( StringUtils.isEmpty( encoding ) && isFilteringEnabled( getResources() ) )
{
getLog().warn( "File encoding has not been set, using platform encoding " + ReaderFactory.FILE_ENCODING
+ ", i.e. build is platform dependent!" );
}
try
{
List combinedFilters = getCombinedFiltersList();
MavenResourcesExecution mavenResourcesExecution =
new MavenResourcesExecution( getResources(), getOutputDirectory(), project, encoding, combinedFilters,
Collections.emptyList(), session );
mavenResourcesExecution.setEscapeWindowsPaths( escapeWindowsPaths );
// never include project build filters in this call, since we've already accounted for the POM build filters
// above, in getCombinedFiltersList().
mavenResourcesExecution.setInjectProjectBuildFilters( false );
mavenResourcesExecution.setEscapeString( escapeString );
mavenResourcesExecution.setOverwrite( overwrite );
mavenResourcesExecution.setIncludeEmptyDirs( includeEmptyDirs );
mavenResourcesExecution.setSupportMultiLineFiltering( supportMultiLineFiltering );
mavenResourcesExecution.setFilterFilenames( fileNameFiltering );
mavenResourcesExecution.setAddDefaultExcludes( addDefaultExcludes );
// Handle subject of MRESOURCES-99
Properties additionalProperties = addSeveralSpecialProperties();
mavenResourcesExecution.setAdditionalProperties( additionalProperties );
// if these are NOT set, just use the defaults, which are '${*}' and '@'.
mavenResourcesExecution.setDelimiters( delimiters, useDefaultDelimiters );
if ( nonFilteredFileExtensions != null )
{
mavenResourcesExecution.setNonFilteredFileExtensions( nonFilteredFileExtensions );
}
mavenResourcesFiltering.filterResources( mavenResourcesExecution );
executeUserFilterComponents( mavenResourcesExecution );
}
catch ( MavenFilteringException e )
{
throw new MojoExecutionException( e.getMessage(), e );
}
}
/**
* This solves https://issues.apache.org/jira/browse/MRESOURCES-99.
* BUT:
* This should be done different than defining those properties a second time, cause they have already being defined
* in Maven Model Builder (package org.apache.maven.model.interpolation) via BuildTimestampValueSource. But those
* can't be found in the context which can be got from the maven core.
* A solution could be to put those values into the context by Maven core so they are accessible everywhere. (I'm
* not sure if this is a good idea). Better ideas are always welcome.
*
* The problem at the moment is that maven core handles usage of properties and replacements in
* the model, but does not the resource filtering which needed some of the properties.
*
* @return the new instance with those properties.
*/
private Properties addSeveralSpecialProperties()
{
String timeStamp = new MavenBuildTimestamp().formattedTimestamp();
Properties additionalProperties = new Properties();
additionalProperties.put( "maven.build.timestamp", timeStamp );
if ( project.getBasedir() != null )
{
additionalProperties.put( "project.baseUri", project.getBasedir().getAbsoluteFile().toURI().toString() );
}
return additionalProperties;
}
/**
* @param mavenResourcesExecution {@link MavenResourcesExecution}
* @throws MojoExecutionException in case of wrong lookup.
* @throws MavenFilteringException in case of failure.
* @since 2.5
*/
protected void executeUserFilterComponents( MavenResourcesExecution mavenResourcesExecution )
throws MojoExecutionException, MavenFilteringException
{
if ( mavenFilteringHints != null )
{
for ( String hint : mavenFilteringHints )
{
try
{
// CHECKSTYLE_OFF: LineLength
mavenFilteringComponents.add( (MavenResourcesFiltering) plexusContainer.lookup( MavenResourcesFiltering.class.getName(),
hint ) );
// CHECKSTYLE_ON: LineLength
}
catch ( ComponentLookupException e )
{
throw new MojoExecutionException( e.getMessage(), e );
}
}
}
else
{
getLog().debug( "no use filter components" );
}
if ( mavenFilteringComponents != null && !mavenFilteringComponents.isEmpty() )
{
getLog().debug( "execute user filters" );
for ( MavenResourcesFiltering filter : mavenFilteringComponents )
{
filter.filterResources( mavenResourcesExecution );
}
}
}
/**
* @return The combined filters.
*/
protected List getCombinedFiltersList()
{
if ( filters == null || filters.isEmpty() )
{
return useBuildFilters ? buildFilters : null;
}
else
{
List result = new ArrayList();
if ( useBuildFilters && buildFilters != null && !buildFilters.isEmpty() )
{
result.addAll( buildFilters );
}
result.addAll( filters );
return result;
}
}
/**
* Determines whether filtering has been enabled for any resource.
*
* @param theResources The set of resources to check for filtering, may be null
.
* @return true
if at least one resource uses filtering, false
otherwise.
*/
private boolean isFilteringEnabled( Collection theResources )
{
if ( theResources != null )
{
for ( Resource resource : theResources )
{
if ( resource.isFiltering() )
{
return true;
}
}
}
return false;
}
/**
* @return {@link #resources}
*/
public List getResources()
{
return resources;
}
/**
* @param resources set {@link #resources}
*/
public void setResources( List resources )
{
this.resources = resources;
}
/**
* @return {@link #outputDirectory}
*/
public File getOutputDirectory()
{
return outputDirectory;
}
/**
* @param outputDirectory the output folder.
*/
public void setOutputDirectory( File outputDirectory )
{
this.outputDirectory = outputDirectory;
}
/**
* @return {@link #overwrite}
*/
public boolean isOverwrite()
{
return overwrite;
}
/**
* @param overwrite true to overwrite false otherwise.
*/
public void setOverwrite( boolean overwrite )
{
this.overwrite = overwrite;
}
/**
* @return {@link #includeEmptyDirs}
*/
public boolean isIncludeEmptyDirs()
{
return includeEmptyDirs;
}
/**
* @param includeEmptyDirs true/false.
*/
public void setIncludeEmptyDirs( boolean includeEmptyDirs )
{
this.includeEmptyDirs = includeEmptyDirs;
}
/**
* @return {@link #filters}
*/
public List getFilters()
{
return filters;
}
/**
* @param filters The filters to use.
*/
public void setFilters( List filters )
{
this.filters = filters;
}
/**
* @return {@link #delimiters}
*/
public LinkedHashSet getDelimiters()
{
return delimiters;
}
/**
* @param delimiters The delimiters to use.
*/
public void setDelimiters( LinkedHashSet delimiters )
{
this.delimiters = delimiters;
}
/**
* @return {@link #useDefaultDelimiters}
*/
public boolean isUseDefaultDelimiters()
{
return useDefaultDelimiters;
}
/**
* @param useDefaultDelimiters true to use {@code ${*}}
*/
public void setUseDefaultDelimiters( boolean useDefaultDelimiters )
{
this.useDefaultDelimiters = useDefaultDelimiters;
}
/**
* @return {@link #skip}
*/
public boolean isSkip()
{
return skip;
}
}