blob: e05d8d40c57f27e52cac06809ddfb56bb5198c5b [file] [log] [blame]
/*
* 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.
*/
package org.apache.myfaces.buildtools.maven2.plugin.builder.unpack;
import java.io.File;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.model.Dependency;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.dependency.utils.DependencyUtil;
import org.apache.maven.plugin.dependency.utils.filters.ArtifactItemFilter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.artifact.filter.collection.ArtifactFilterException;
import org.codehaus.plexus.util.StringUtils;
/**
* Abstract Parent class used by mojos that get Artifact information from the plugin configuration as an ArrayList of
* ArtifactItems
*
* @see ArtifactItem
* @author <a href="mailto:brianf@apache.org">Brian Fox</a>
* @version $Id$
*/
public abstract class AbstractFromConfigurationMojo
extends AbstractDependencyMojo
{
/**
* Skip the execution
*
* @optional
* @since 2.2
* @parameter expression="${mdep.skip}" default-value="false"
*/
private boolean skip;
/**
* Default location used for mojo unless overridden in ArtifactItem
*
* @parameter expression="${outputDirectory}" default-value="${project.build.directory}/dependency"
* @optional
* @since 1.0
*/
private File outputDirectory;
/**
* Overwrite release artifacts
*
* @optional
* @since 1.0
* @parameter expression="${mdep.overWriteReleases}" default-value="false"
*/
private boolean overWriteReleases;
/**
* Overwrite snapshot artifacts
*
* @optional
* @since 1.0
* @parameter expression="${mdep.overWriteSnapshots}" default-value="false"
*/
private boolean overWriteSnapshots;
/**
* Overwrite if newer
*
* @optional
* @since 2.0
* @parameter expression="${mdep.overIfNewer}" default-value="true"
*/
private boolean overWriteIfNewer;
/**
* To search for artifacts within the reactor and ensure consistent behaviour between Maven 2 and Maven 3.
*
* @parameter expression="${reactorProjects}"
* @required
* @readonly
*/
protected List<MavenProject> reactorProjects;
/**
* Collection of ArtifactItems to work on. (ArtifactItem contains groupId, artifactId, version, type, classifier,
* location, destFileName, markerFile and overwrite.) See <a href="./usage.html">Usage</a> for details.
*
* @parameter
* @required
* @since 1.0
*/
private List<ArtifactItem> artifactItems;
/**
* To look up ArtifactRepository implementation
*
* @component
* @readonly
*/
private ArtifactRepositoryFactory artifactRepositoryManager;
/**
* Path to override default local repository during plugin's execution. To remove all downloaded artifacts as part
* of the build, set this value to a location under your project's target directory
*
* @parameter
* @since 2.2
*/
private File localRepositoryDirectory;
/**
* To host and cache localRepositoryDirectory
*/
private ArtifactRepository overrideLocalRepository;
abstract ArtifactItemFilter getMarkedArtifactFilter( ArtifactItem item );
/**
* Preprocesses the list of ArtifactItems. This method defaults the outputDirectory if not set and creates the
* output Directory if it doesn't exist.
*
* @param removeVersion remove the version from the filename.
* @return An ArrayList of preprocessed ArtifactItems
* @throws MojoExecutionException with a message if an error occurs.
* @see ArtifactItem
*/
protected List<ArtifactItem> getProcessedArtifactItems( boolean removeVersion )
throws MojoExecutionException
{
if ( artifactItems == null || artifactItems.size() < 1 )
{
throw new MojoExecutionException( "There are no artifactItems configured." );
}
for ( ArtifactItem artifactItem : artifactItems )
{
this.getLog().info( "Configured Artifact: " + artifactItem.toString() );
if ( artifactItem.getOutputDirectory() == null )
{
artifactItem.setOutputDirectory( this.outputDirectory );
}
artifactItem.getOutputDirectory().mkdirs();
// make sure we have a version.
if ( StringUtils.isEmpty( artifactItem.getVersion() ) )
{
fillMissingArtifactVersion( artifactItem );
}
artifactItem.setArtifact( this.getArtifact( artifactItem ) );
if ( StringUtils.isEmpty( artifactItem.getDestFileName() ) )
{
artifactItem.setDestFileName( DependencyUtil.getFormattedFileName( artifactItem.getArtifact(),
removeVersion ) );
}
try
{
artifactItem.setNeedsProcessing( checkIfProcessingNeeded( artifactItem ) );
}
catch ( ArtifactFilterException e )
{
throw new MojoExecutionException( e.getMessage(), e );
}
}
return artifactItems;
}
private boolean checkIfProcessingNeeded( ArtifactItem item )
throws MojoExecutionException, ArtifactFilterException
{
boolean result = false;
if ( StringUtils.equalsIgnoreCase( item.getOverWrite(), "true" ) )
{
result = true;
}
else
{
ArtifactItemFilter filter = getMarkedArtifactFilter( item );
result = filter.isArtifactIncluded( item );
}
return result;
}
/**
* Resolves the Artifact from the remote repository if necessary. If no version is specified, it will be retrieved
* from the dependency list or from the DependencyManagement section of the pom.
*
* @param artifactItem containing information about artifact from plugin configuration.
* @return Artifact object representing the specified file.
* @throws MojoExecutionException with a message if the version can't be found in DependencyManagement.
*/
protected Artifact getArtifact( ArtifactItem artifactItem )
throws MojoExecutionException
{
Artifact artifact;
// Map managedVersions = createManagedVersionMap( factory,
// project.getId(), project.getDependencyManagement() );
VersionRange vr;
try
{
vr = VersionRange.createFromVersionSpec( artifactItem.getVersion() );
}
catch ( InvalidVersionSpecificationException e1 )
{
// TODO Auto-generated catch block
e1.printStackTrace();
vr = VersionRange.createFromVersion( artifactItem.getVersion() );
}
if ( StringUtils.isEmpty( artifactItem.getClassifier() ) )
{
artifact =
factory.createDependencyArtifact( artifactItem.getGroupId(), artifactItem.getArtifactId(), vr,
artifactItem.getType(), null, Artifact.SCOPE_COMPILE );
}
else
{
artifact =
factory.createDependencyArtifact( artifactItem.getGroupId(), artifactItem.getArtifactId(), vr,
artifactItem.getType(), artifactItem.getClassifier(),
Artifact.SCOPE_COMPILE );
}
// Maven 3 will search the reactor for the artifact but Maven 2 does not
// to keep consistent behaviour, we search the reactor ourselves.
Artifact result = getArtifactFomReactor( artifact );
if ( result != null )
{
return result;
}
try
{
// mdep-50 - rolledback for now because it's breaking some functionality.
/*
* List listeners = new ArrayList(); Set theSet = new HashSet(); theSet.add( artifact );
* ArtifactResolutionResult artifactResolutionResult = artifactCollector.collect( theSet, project
* .getArtifact(), managedVersions, this.local, project.getRemoteArtifactRepositories(),
* artifactMetadataSource, null, listeners ); Iterator iter =
* artifactResolutionResult.getArtifactResolutionNodes().iterator(); while ( iter.hasNext() ) {
* ResolutionNode node = (ResolutionNode) iter.next(); artifact = node.getArtifact(); }
*/
resolver.resolve( artifact, remoteRepos, getLocal() );
}
catch ( ArtifactResolutionException e )
{
throw new MojoExecutionException( "Unable to resolve artifact.", e );
}
catch ( ArtifactNotFoundException e )
{
throw new MojoExecutionException( "Unable to find artifact.", e );
}
return artifact;
}
/**
* Checks to see if the specified artifact is available from the reactor.
* @param artifact The artifact we are looking for.
* @return The resolved artifact that is the same as the one we were looking for or <code>null</code> if one could
* not be found.
*/
private Artifact getArtifactFomReactor( Artifact artifact )
{
// check project dependencies first off
for ( Artifact a : (Set<Artifact>) project.getArtifacts() )
{
if ( equals( artifact, a ) && hasFile( a ) )
{
return a;
}
}
// check reactor projects
for ( MavenProject p : reactorProjects == null ? Collections.<MavenProject>emptyList() : reactorProjects )
{
// check the main artifact
if ( equals( artifact, p.getArtifact() ) && hasFile( p.getArtifact() ) )
{
return p.getArtifact();
}
// check any side artifacts
for ( Artifact a : (List<Artifact>) p.getAttachedArtifacts() )
{
if ( equals( artifact, a ) && hasFile( a ) )
{
return a;
}
}
}
// not available
return null;
}
/**
* Returns <code>true</code> if the artifact has a file.
* @param artifact the artifact (may be null)
* @return <code>true</code> if and only if the artifact is non-null and has a file.
*/
private static boolean hasFile( Artifact artifact )
{
return artifact != null && artifact.getFile() != null && artifact.getFile().isFile();
}
/**
* Null-safe compare of two artifacts based on groupId, artifactId, version, type and classifier.
* @param a the first artifact.
* @param b the second artifact.
* @return <code>true</code> if and only if the two artifacts have the same groupId, artifactId, version,
* type and classifier.
*/
private static boolean equals( Artifact a, Artifact b )
{
return a == b
|| !( a == null || b == null )
&& StringUtils.equals( a.getGroupId(), b.getGroupId() )
&& StringUtils.equals( a.getArtifactId(), b.getArtifactId() )
&& StringUtils.equals( a.getVersion(), b.getVersion() )
&& StringUtils.equals( a.getType(), b.getType() )
&& StringUtils.equals( a.getClassifier(), b.getClassifier() );
}
/**
* Tries to find missing version from dependency list and dependency management. If found, the artifact is updated
* with the correct version. It will first look for an exact match on artifactId/groupId/classifier/type and if it
* doesn't find a match, it will try again looking for artifactId and groupId only.
*
* @param artifact representing configured file.
* @throws MojoExecutionException
*/
private void fillMissingArtifactVersion( ArtifactItem artifact )
throws MojoExecutionException
{
List<Dependency> deps = project.getDependencies();
List<Dependency> depMngt = project.getDependencyManagement() == null
? Collections.<Dependency>emptyList()
: project.getDependencyManagement().getDependencies();
if ( !findDependencyVersion( artifact, deps, false )
&& ( project.getDependencyManagement() == null || !findDependencyVersion( artifact, depMngt, false ) )
&& !findDependencyVersion( artifact, deps, true )
&& ( project.getDependencyManagement() == null || !findDependencyVersion( artifact, depMngt, true ) ) )
{
throw new MojoExecutionException( "Unable to find artifact version of " + artifact.getGroupId() + ":"
+ artifact.getArtifactId() + " in either dependency list or in project's dependency management." );
}
}
/**
* Tries to find missing version from a list of dependencies. If found, the artifact is updated with the correct
* version.
*
* @param artifact representing configured file.
* @param dependencies list of dependencies to search.
* @param looseMatch only look at artifactId and groupId
* @return the found dependency
*/
private boolean findDependencyVersion( ArtifactItem artifact, List<Dependency> dependencies, boolean looseMatch )
{
for ( Dependency dependency : dependencies )
{
if ( StringUtils.equals( dependency.getArtifactId(), artifact.getArtifactId() )
&& StringUtils.equals( dependency.getGroupId(), artifact.getGroupId() )
&& ( looseMatch || StringUtils.equals( dependency.getClassifier(), artifact.getClassifier() ) )
&& ( looseMatch || StringUtils.equals( dependency.getType(), artifact.getType() ) ) )
{
artifact.setVersion( dependency.getVersion() );
return true;
}
}
return false;
}
/*
* private Map createManagedVersionMap( ArtifactFactory artifactFactory, String projectId, DependencyManagement
* dependencyManagement ) throws MojoExecutionException { Map map; if ( dependencyManagement != null &&
* dependencyManagement.getDependencies() != null ) { map = new HashMap(); for ( Iterator i =
* dependencyManagement.getDependencies().iterator(); i.hasNext(); ) { Dependency d = (Dependency) i.next(); try {
* VersionRange versionRange = VersionRange.createFromVersionSpec( d.getVersion() ); Artifact artifact =
* artifactFactory.createDependencyArtifact( d.getGroupId(), d.getArtifactId(), versionRange, d.getType(), d
* .getClassifier(), d.getScope(), d .isOptional() ); map.put( d.getManagementKey(), artifact ); } catch (
* InvalidVersionSpecificationException e ) { throw new MojoExecutionException( "Unable to parse version", e ); } }
* } else { map = Collections.EMPTY_MAP; } return map; }
*/
/**
* Override the base to
*
* @return Returns the local.
*/
protected ArtifactRepository getLocal()
{
if ( this.overrideLocalRepository != null )
{
return this.overrideLocalRepository;
}
ArtifactRepository local = super.getLocal();
if ( this.localRepositoryDirectory != null )
{
// create a new local repo using existing layout, snapshots, and releases policy
String url = "file://" + this.localRepositoryDirectory.getAbsolutePath();
this.overrideLocalRepository =
artifactRepositoryManager.createArtifactRepository( local.getId(), url, local.getLayout(),
local.getSnapshots(), local.getReleases() );
this.getLog().debug( "Execution local repository is at: " + this.overrideLocalRepository.getBasedir() );
}
else
{
this.overrideLocalRepository = local;
}
return this.overrideLocalRepository;
}
/**
* @return Returns the artifactItems.
*/
public List<ArtifactItem> getArtifactItems()
{
return this.artifactItems;
}
/**
* @param theArtifactItems The artifactItems to set.
*/
public void setArtifactItems( List<ArtifactItem> theArtifactItems )
{
this.artifactItems = theArtifactItems;
}
/**
* @return Returns the outputDirectory.
*/
public File getOutputDirectory()
{
return this.outputDirectory;
}
/**
* @param theOutputDirectory The outputDirectory to set.
*/
public void setOutputDirectory( File theOutputDirectory )
{
this.outputDirectory = theOutputDirectory;
}
/**
* @return Returns the overWriteIfNewer.
*/
public boolean isOverWriteIfNewer()
{
return this.overWriteIfNewer;
}
/**
* @param theOverWriteIfNewer The overWriteIfNewer to set.
*/
public void setOverWriteIfNewer( boolean theOverWriteIfNewer )
{
this.overWriteIfNewer = theOverWriteIfNewer;
}
/**
* @return Returns the overWriteReleases.
*/
public boolean isOverWriteReleases()
{
return this.overWriteReleases;
}
/**
* @param theOverWriteReleases The overWriteReleases to set.
*/
public void setOverWriteReleases( boolean theOverWriteReleases )
{
this.overWriteReleases = theOverWriteReleases;
}
/**
* @return Returns the overWriteSnapshots.
*/
public boolean isOverWriteSnapshots()
{
return this.overWriteSnapshots;
}
/**
* @param theOverWriteSnapshots The overWriteSnapshots to set.
*/
public void setOverWriteSnapshots( boolean theOverWriteSnapshots )
{
this.overWriteSnapshots = theOverWriteSnapshots;
}
public void setLocalRepositoryDirectory( File localRepositoryDirectory )
{
this.localRepositoryDirectory = localRepositoryDirectory;
}
public boolean isSkip()
{
return skip;
}
public void setSkip( boolean skip )
{
this.skip = skip;
}
}