org.codehaus.mojo.unix.maven.MojoHelper Maven / Gradle / Ivy
package org.codehaus.mojo.unix.maven;
/*
* The MIT License
*
* Copyright 2009 The Codehaus.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import fj.*;
import static fj.Function.*;
import static fj.Ord.*;
import static fj.P.*;
import fj.data.List;
import static fj.data.List.join;
import static fj.data.List.*;
import static fj.data.List.single;
import fj.data.*;
import static fj.data.Option.*;
import fj.data.Set;
import static fj.data.Set.*;
import static java.lang.String.*;
import org.apache.commons.logging.*;
import org.apache.commons.vfs.*;
import org.apache.maven.artifact.*;
import org.apache.maven.plugin.*;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.*;
import org.codehaus.mojo.unix.*;
import static org.codehaus.mojo.unix.PackageParameters.*;
import org.codehaus.mojo.unix.core.*;
import org.codehaus.mojo.unix.java.*;
import static org.codehaus.mojo.unix.java.StringF.*;
import org.codehaus.mojo.unix.maven.logging.*;
import org.codehaus.mojo.unix.maven.plugin.*;
import org.codehaus.mojo.unix.maven.plugin.Package;
import static org.codehaus.mojo.unix.util.FileModulator.*;
import org.codehaus.mojo.unix.util.*;
import org.codehaus.mojo.unix.util.line.*;
import java.io.*;
import java.text.*;
import java.util.*;
import java.util.TreeMap;
/**
* Utility class encapsulating how to create a package. Used by all packaging Mojos.
*
* @author Trygve Laugstøl
*/
public abstract class MojoHelper
{
public static final String ATTACHED_NO_ARTIFACTS_CONFIGURED = "When running in attached mode at least one package has to be configured.";
public static final String DUPLICATE_CLASSIFIER = "Duplicate package classifier: '%s'.";
public static final String DUPLICATE_UNCLASSIFIED = "There can only be one package without an classifier.";
public static Execution create( Map platforms,
String platformType,
Map formats,
String formatType,
MavenProjectWrapper project,
boolean debug,
boolean attachedMode,
F validateMojoSettingsAndApplyFormatSpecificSettingsToPackage,
PackagingMojoParameters mojoParameters,
final Log log )
throws MojoFailureException, MojoExecutionException
{
MavenCommonLoggingLogFactory.setMavenLogger( log );
PackagingFormat format = (PackagingFormat) formats.get( formatType );
if ( format == null )
{
throw new MojoFailureException( "INTERNAL ERROR: could not find format: '" + formatType + "'." );
}
UnixPlatform platform = (UnixPlatform) platforms.get( platformType );
if ( platform == null )
{
throw new MojoFailureException( "INTERNAL ERROR: could not find platform: '" + platformType + "'." );
}
/*
// TODO: This is using a private Maven API that might change. Perhaps use some reflection magic here.
String timestamp = snapshotTransformation.getDeploymentTimestamp();
*/
// This chunk replaces the above getDeploymentTimestamp. However, it not ensure that all files get the
// same timestamp. Need to look into how this is done with Maven 3
DateFormat utcDateFormatter = new SimpleDateFormat( "yyyyMMdd.HHmmss" );
utcDateFormatter.setTimeZone( TimeZone.getTimeZone( "UTC" ) );
String timestamp = utcDateFormatter.format( new Date() );
FileObject buildDirectory;
try
{
FileSystemManager fileSystemManager = VFS.getManager();
buildDirectory = fileSystemManager.resolveFile( project.buildDirectory.getAbsolutePath() );
}
catch ( FileSystemException e )
{
throw new MojoExecutionException( "Error while initializing Commons VFS", e );
}
PackageVersion version = PackageVersion.packageVersion( project.version, timestamp,
project.artifact.isSnapshot(), mojoParameters.revision );
List>> packages = nil();
for ( Package pakke : validatePackages( mojoParameters.packages, attachedMode ) )
{
try
{
String name = "unix/root-" + formatType + pakke.classifier.map( dashString ).orSome( "" );
FileObject packageRoot = buildDirectory.resolveFile( name );
packageRoot.createFolder();
PackageParameters parameters = calculatePackageParameters( project,
version,
platform,
mojoParameters,
pakke );
UnixPackage unixPackage = format.start().
parameters( parameters ).
setVersion( version ). // TODO: This should go away
workingDirectory( packageRoot ).
debug( debug ).
basedir( project.basedir );
// -----------------------------------------------------------------------
// Let the implementation add its metadata
// -----------------------------------------------------------------------
unixPackage = validateMojoSettingsAndApplyFormatSpecificSettingsToPackage.f( unixPackage );
// TODO: here the logic should be different if many packages are to be created.
// Example: name should be taken from mojoParameters if there is only a single package, if not
// it should come from the Pakke object. This should also be validated, at least for
// name
List assemblyOperations = createAssemblyOperations( project,
parameters,
unixPackage,
project.basedir,
buildDirectory,
mojoParameters.assembly,
pakke.assembly );
// -----------------------------------------------------------------------
// Dump the execution
// -----------------------------------------------------------------------
if ( debug )
{
log.info( "=======================================================================" );
log.info( "Package parameters: " + parameters.id );
log.info( "Default file attributes: " );
log.info( " File : " + parameters.defaultFileAttributes );
log.info( " Directory : " + parameters.defaultDirectoryAttributes );
log.info( "Assembly operations: " );
for ( AssemblyOperation operation : assemblyOperations )
{
operation.streamTo( new AbstractLineStreamWriter()
{
protected void onLine( String line )
{
log.info( line );
}
} );
}
}
packages = packages.cons( p( unixPackage, pakke, assemblyOperations ) );
}
catch ( UnknownArtifactException e )
{
Map map = new TreeMap( e.artifactMap );
// TODO: Do not log here, throw a CouldNotFindArtifactException with the map as an argument
log.warn( "Could not find artifact:" + e.artifact );
log.warn( "Available artifacts:" );
for ( Object o : map.keySet() )
{
log.warn( o.toString() );
}
throw new MojoFailureException( "Unable to find artifact: '" + e.artifact + "'. See log for available artifacts." );
}
catch ( MissingSettingException e )
{
String msg = "Missing required setting '" + e.getSetting() + "'";
if ( !pakke.classifier.isNone() )
{
msg += ", for '" + pakke.classifier.some() + "'";
}
msg += ", format '" + formatType + "'.";
throw new MojoFailureException( msg );
}
catch ( IOException e )
{
throw new MojoExecutionException( "Error creating package " + (pakke.classifier.isSome() ? "classifier '" + pakke.classifier + "'" : "") + ", format '" + formatType + "'.", e );
}
}
return new Execution( packages, project, formatType, attachedMode );
}
public static class Execution
{
private final List>> packages;
private final MavenProjectWrapper project;
private final String formatType;
private final boolean attachedMode;
public Execution( List>> packages, MavenProjectWrapper project,
String formatType, boolean attachedMode )
{
this.packages = packages;
this.project = project;
this.formatType = formatType;
this.attachedMode = attachedMode;
}
public void execute( String artifactType, MavenProject mavenProject, MavenProjectHelper mavenProjectHelper, ScriptUtil.Strategy strategy )
throws MojoExecutionException, MojoFailureException
{
// Save and restore the system property for commons logging.
String key = LogFactory.class.getName();
String value = System.getProperty( key );
System.setProperty( key, MavenCommonLoggingLogFactory.class.getName() );
try
{
execute_( artifactType, mavenProject, mavenProjectHelper, strategy );
}
finally {
if(value == null) {
System.getProperties().remove( key );
}
else {
System.setProperty( key, value );
}
}
}
private void execute_( String artifactType, MavenProject mavenProject, MavenProjectHelper mavenProjectHelper, ScriptUtil.Strategy strategy )
throws MojoExecutionException, MojoFailureException
{
for ( P3> p : packages )
{
UnixPackage unixPackage = p._1();
Package pakke = p._2();
try
{
// -----------------------------------------------------------------------
// Assemble all the files
// -----------------------------------------------------------------------
for ( AssemblyOperation assemblyOperation : p._3() )
{
assemblyOperation.perform( unixPackage );
}
// -----------------------------------------------------------------------
// Package the stuff
// -----------------------------------------------------------------------
String name = project.artifactId +
pakke.classifier.map( dashString ).orSome( "" ) +
"-" + unixPackage.getVersion().getMavenVersion() +
"." + unixPackage.getPackageFileExtension();
File packageFile = new File( project.buildDirectory, name );
unixPackage.
packageToFile( packageFile, strategy );
attach( pakke.classifier, artifactType, packageFile, mavenProject, mavenProjectHelper,
attachedMode );
}
catch ( MojoExecutionException e )
{
throw e;
}
catch ( MojoFailureException e )
{
throw e;
}
catch ( Exception e )
{
throw new MojoExecutionException( "Unable to create package.", e );
}
}
}
private void attach( Option classifier, String artifactType, File packageFile,
MavenProject project, MavenProjectHelper mavenProjectHelper, boolean attachedMode )
{
if ( attachedMode )
{
// In attached mode all the packages are required to have an classifier - this used to be correct - trygve
// For some reason it is allowed to have attached artifacts without classifier as long as the types differ
if ( classifier.isSome() )
{
mavenProjectHelper.attachArtifact( project, artifactType, classifier.some(), packageFile );
}
else
{
mavenProjectHelper.attachArtifact( project, artifactType, null, packageFile );
}
}
else
{
if ( classifier.isNone() )
{
project.getArtifact().setFile( packageFile );
}
else
{
mavenProjectHelper.attachArtifact( project, formatType, classifier.some(), packageFile );
}
}
}
}
public static PackageParameters calculatePackageParameters( final MavenProjectWrapper project,
PackageVersion version,
UnixPlatform platform,
PackagingMojoParameters mojoParameters,
final Package pakke )
{
String id = pakke.id.orSome( new P1()
{
public String _1()
{
// This used to be ${groupId}-${artifactId}, but it was too long for pkg so this is a more sane default
return project.artifactId + pakke.classifier.map( dashString ).orSome( "" );
}
} );
P2 defaultFileAttributes =
calculateDefaultFileAttributes( platform,
mojoParameters.defaults,
pakke.defaults );
String name = pakke.name.orElse( mojoParameters.name ).orSome( project.name );
return packageParameters( project.groupId, project.artifactId, version, id, name, pakke.classifier, defaultFileAttributes._1(), defaultFileAttributes._2() ).
description( pakke.description.orElse( mojoParameters.description ).orElse( project.description ) ).
contact( mojoParameters.contact ).
contactEmail( mojoParameters.contactEmail ).
license( getLicense( project ) ).
architecture( pakke.architecture.orElse( mojoParameters.architecture ) );
}
public static P2 calculateDefaultFileAttributes( UnixPlatform platform,
Defaults mojo,
Defaults pakke )
{
return p( calculateFileAttributes( platform.getDefaultFileAttributes(),
mojo.fileAttributes.create(),
pakke.fileAttributes.create() ),
calculateFileAttributes( platform.getDefaultDirectoryAttributes(),
mojo.directoryAttributes.create(),
pakke.directoryAttributes.create() ) );
}
public static FileAttributes calculateFileAttributes( FileAttributes platform,
FileAttributes mojo,
FileAttributes pakke )
{
// Calculate default file and directory attributes.
// Priority order (last one wins): platform -> mojo defaults -> package defaults
return platform.
useAsDefaultsFor( mojo ).
useAsDefaultsFor( pakke );
}
public static List createAssemblyOperations( MavenProjectWrapper project,
PackageParameters parameters,
UnixPackage unixPackage,
File basedir,
FileObject buildDirectory,
List mojoAssembly,
List packageAssembly )
throws IOException, MojoFailureException, UnknownArtifactException
{
unixPackage.beforeAssembly( parameters.defaultDirectoryAttributes );
// Create the default set of assembly operations
String unix = new File( basedir, "src/main/unix/files" ).getAbsolutePath();
String classifierOrDefault = parameters.classifier.orSome( "default" );
List defaultAssemblyOp = nil();
// It would be possible to use the AssemblyOperations here but this just make it easier to document
// as it has a one-to-one relationship with what the user would configure in a POM
for ( String s : modulatePath( classifierOrDefault, unixPackage.getPackageFileExtension(), unix ) )
{
File file = new File( s );
if ( !file.isDirectory() )
{
continue;
}
CopyDirectory op = new CopyDirectory();
op.setFrom( file );
defaultAssemblyOp = defaultAssemblyOp.cons( op );
}
// Create the complete list of assembly operations.
// Order: defaults -> mojo -> pakke
List assemblyOps = join( list( defaultAssemblyOp.reverse(), mojoAssembly, packageAssembly ) );
List operations = nil();
for ( AssemblyOp assemblyOp : assemblyOps )
{
assemblyOp.setArtifactMap( project.artifactConflictIdMap );
AssemblyOperation operation = assemblyOp.createOperation( buildDirectory,
parameters.defaultFileAttributes,
parameters.defaultDirectoryAttributes );
operations = operations.cons( operation );
}
return operations.reverse();
}
public static List validatePackages( List packages, boolean attachedMode )
throws MojoFailureException
{
if ( packages.isEmpty() )
{
packages = single( new Package() );
}
Set names = empty( stringOrd );
List outPackages = nil();
Option defaultPackage = none();
for ( Package pakke : packages )
{
if ( pakke.classifier.exists( curry( StringF.equals, "default" ) ) )
{
pakke.classifier = none();
}
if ( pakke.classifier.isNone() )
{
if ( defaultPackage.isSome() )
{
throw new MojoFailureException( DUPLICATE_UNCLASSIFIED );
}
defaultPackage = some( pakke );
}
else
{
if ( names.member( pakke.classifier.some() ) )
{
throw new MojoFailureException( format( DUPLICATE_CLASSIFIER, pakke.classifier ) );
}
names = names.insert( pakke.classifier.some() );
outPackages = outPackages.cons( pakke );
}
}
if ( attachedMode )
{
outPackages = defaultPackage.toList().append( outPackages );
if ( outPackages.isEmpty() )
{
throw new MojoFailureException( ATTACHED_NO_ARTIFACTS_CONFIGURED );
}
return outPackages;
}
if ( defaultPackage.isNone() )
{
throw new MojoFailureException( "When running in 'primary artifact mode' either one package has to have 'default' as classifier or there has to be one without any classifier." );
}
return defaultPackage.toList().append( outPackages );
}
private static Option getLicense( MavenProjectWrapper project )
{
if ( project.licenses.size() == 0 )
{
return none();
}
return some( project.licenses.get( 0 ).getName() );
}
static F dashString = curry( concat, "-" );
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy