o Fixed tabs -> spaces (sorry, makes diff hard to read) and some codingstyle

issues.

o Modified model: added a 'BaseSet' type as a basetype
  for DependencySet and FileSet; it contains fileMode and
  directoryMode to work with the new plexus-archiver.

o Bumped plexus-archiver version to 1.0-alpha-2-SNAPSHOT.

o Added support for actually using fileMode and directoryMode.
  (tested this with a modified maven-core assembly descriptor,
  not committed as a test though).



git-svn-id: https://svn.apache.org/repos/asf/maven/components/trunk@264888 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Kenney Westerhof 2005-08-30 22:57:50 +00:00
parent e0457b0204
commit 6fdbe554dd
3 changed files with 412 additions and 369 deletions

View File

@ -44,7 +44,7 @@
<dependency>
<groupId>plexus</groupId>
<artifactId>plexus-archiver</artifactId>
<version>1.0-alpha-1</version>
<version>1.0-alpha-2-SNAPSHOT</version>
</dependency>
</dependencies>
<developers>

View File

@ -36,6 +36,7 @@ import org.codehaus.plexus.archiver.tar.TarArchiver;
import org.codehaus.plexus.archiver.zip.ZipArchiver;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.introspection.ReflectionValueExtractor;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import java.io.File;
import java.io.FileReader;
@ -64,21 +65,23 @@ public class AssemblyMojo
extends AbstractUnpackingMojo
{
/**
* @parameter expression="${maven.assembly.descriptorId}"
*/
protected String descriptorId;
/**
* @parameter expression="${maven.assembly.descriptor}"
*/
protected File descriptor;
/**
* @parameter expression="${basedir}"
* @required
* @readonly
*/
private String basedir;
/**
* @parameter expression="${maven.assembly.descriptorId}"
*/
protected String descriptorId;
/**
* @parameter expression="${maven.assembly.descriptor}"
*/
protected File descriptor;
/**
* @parameter expression="${basedir}"
* @required
* @readonly
*/
private String basedir;
/**
* @parameter expression="${project}"
* @required
@ -93,337 +96,370 @@ public class AssemblyMojo
*/
private MavenProjectHelper projectHelper;
public void execute() throws MojoExecutionException {
try
{
doExecute();
}
catch ( Exception e )
{
// TODO: don't catch exception
throw new MojoExecutionException( "Error creating assembly", e );
}
}
public void execute()
throws MojoExecutionException
{
try
{
doExecute();
}
catch ( Exception e )
{
// TODO: don't catch exception
throw new MojoExecutionException( "Error creating assembly", e );
}
}
private void doExecute() throws Exception {
Reader r = null;
if ( descriptor != null )
{
r = new FileReader( descriptor );
}
else if ( descriptorId != null )
{
InputStream resourceAsStream = getClass().getResourceAsStream( "/assemblies/" + descriptorId + ".xml" );
if ( resourceAsStream == null )
{
throw new MojoExecutionException( "Descriptor with ID '" + descriptorId + "' not found" );
}
r = new InputStreamReader( resourceAsStream );
}
else
{
// TODO: better exception
throw new MojoExecutionException( "You must specify descriptor or descriptorId" );
}
try
{
AssemblyXpp3Reader reader = new AssemblyXpp3Reader();
Assembly assembly = reader.read( r );
// TODO: include dependencies marked for distribution under certain formats
// TODO: how, might we plug this into an installer, such as NSIS?
// TODO: allow file mode specifications?
String fullName = finalName + "-" + assembly.getId();
for ( Iterator i = assembly.getFormats().iterator(); i.hasNext(); )
{
String format = (String) i.next();
String filename = fullName + "." + format;
// TODO: use component roles? Can we do that in a mojo?
Archiver archiver = createArchiver( format );
processFileSets( archiver, assembly.getFileSets(), assembly.isIncludeBaseDirectory() );
processDependencySets( archiver, assembly.getDependencySets(), assembly.isIncludeBaseDirectory() );
File destFile = new File( outputDirectory, filename );
archiver.setDestFile( destFile );
archiver.createArchive();
private void doExecute()
throws ArchiverException, IOException, MojoExecutionException, XmlPullParserException
{
Reader r = null;
if ( descriptor != null )
{
r = new FileReader( descriptor );
}
else if ( descriptorId != null )
{
InputStream resourceAsStream = getClass().getResourceAsStream( "/assemblies/" + descriptorId + ".xml" );
if ( resourceAsStream == null )
{
throw new MojoExecutionException( "Descriptor with ID '" + descriptorId + "' not found" );
}
r = new InputStreamReader( resourceAsStream );
}
else
{
// TODO: better exception
throw new MojoExecutionException( "You must specify descriptor or descriptorId" );
}
try
{
AssemblyXpp3Reader reader = new AssemblyXpp3Reader();
Assembly assembly = reader.read( r );
// TODO: include dependencies marked for distribution under certain formats
// TODO: how, might we plug this into an installer, such as NSIS?
// TODO: allow file mode specifications?
String fullName = finalName + "-" + assembly.getId();
for ( Iterator i = assembly.getFormats().iterator(); i.hasNext(); )
{
String format = (String) i.next();
String filename = fullName + "." + format;
// TODO: use component roles? Can we do that in a mojo?
Archiver archiver = createArchiver( format );
processFileSets( archiver, assembly.getFileSets(), assembly.isIncludeBaseDirectory() );
processDependencySets( archiver, assembly.getDependencySets(), assembly.isIncludeBaseDirectory() );
File destFile = new File( outputDirectory, filename );
archiver.setDestFile( destFile );
archiver.createArchive();
projectHelper.attachArtifact(project, format, format + "-assembly", destFile );
}
}
finally
{
IOUtil.close( r );
}
}
}
}
finally
{
IOUtil.close( r );
}
}
private void processDependencySets(Archiver archiver, List dependencySets, boolean includeBaseDirectory) throws ArchiverException, IOException, Exception {
for ( Iterator i = dependencySets.iterator(); i.hasNext(); )
{
DependencySet dependencySet = (DependencySet) i.next();
String output = dependencySet.getOutputDirectory();
output = getOutputDirectory( output, includeBaseDirectory );
AndArtifactFilter filter = new AndArtifactFilter();
filter.add( new ScopeArtifactFilter( dependencySet.getScope() ) );
if ( !dependencySet.getIncludes().isEmpty() )
{
filter.add( new IncludesArtifactFilter( dependencySet.getIncludes() ) );
}
if ( !dependencySet.getExcludes().isEmpty() )
{
filter.add( new ExcludesArtifactFilter( dependencySet.getExcludes() ) );
}
// TODO: includes and excludes
for ( Iterator j = dependencies.iterator(); j.hasNext(); )
{
Artifact artifact = (Artifact) j.next();
if ( filter.include( artifact ) )
{
String name = artifact.getFile().getName();
if ( dependencySet.isUnpack() )
{
// TODO: something like zipfileset in plexus-archiver
// archiver.addJar( )
File tempLocation = new File( workDirectory, name.substring( 0, name.length() - 4 ) );
boolean process = false;
if ( !tempLocation.exists() )
{
tempLocation.mkdirs();
process = true;
}
else if ( artifact.getFile().lastModified() > tempLocation.lastModified() )
{
process = true;
}
if ( process )
{
unpack( artifact.getFile(), tempLocation );
}
archiver.addDirectory( tempLocation, null,
(String[]) getJarExcludes().toArray( EMPTY_STRING_ARRAY ) );
}
else
{
archiver.addFile( artifact.getFile(), output +
evaluateFileNameMapping( dependencySet.getOutputFileNameMapping(), artifact ) );
}
}
}
}
}
private void processDependencySets( Archiver archiver, List dependencySets, boolean includeBaseDirectory )
throws ArchiverException, IOException, MojoExecutionException
{
for ( Iterator i = dependencySets.iterator(); i.hasNext(); )
{
DependencySet dependencySet = (DependencySet) i.next();
String output = dependencySet.getOutputDirectory();
output = getOutputDirectory( output, includeBaseDirectory );
private void processFileSets(Archiver archiver, List fileSets, boolean includeBaseDirecetory) throws ArchiverException {
for ( Iterator i = fileSets.iterator(); i.hasNext(); )
{
FileSet fileSet = (FileSet) i.next();
String directory = fileSet.getDirectory();
String output = fileSet.getOutputDirectory();
if ( directory == null )
{
directory = basedir;
if ( output == null )
{
output = "";
}
}
else
{
if ( output == null )
{
output = directory;
}
}
output = getOutputDirectory( output, includeBaseDirecetory );
String[] includes = (String[]) fileSet.getIncludes().toArray( EMPTY_STRING_ARRAY );
if ( includes.length == 0 )
{
includes = null;
}
List excludesList = fileSet.getExcludes();
excludesList.addAll( getDefaultExcludes() );
String[] excludes = (String[]) excludesList.toArray( EMPTY_STRING_ARRAY );
// TODO: default excludes should be in the archiver?
archiver.addDirectory( new File( directory ), output, includes, excludes );
}
}
private String evaluateFileNameMapping( String expression, Artifact artifact )
throws Exception
{
// this matches the last ${...} string
Pattern pat = Pattern.compile( "^(.*)\\$\\{([^\\}]+)\\}(.*)$" );
Matcher mat = pat.matcher( expression );
String left,right;
Object middle;
if ( mat.matches() )
{
left = evaluateFileNameMapping( mat.group( 1 ), artifact );
middle = ReflectionValueExtractor.evaluate( "dep." + mat.group( 2 ), artifact );
right = mat.group( 3 );
if ( middle == null )
{
// TODO: There should be a more generic way dealing with that. Having magic words is not good at all.
// probe for magic word
if ( mat.group( 2 ).trim().equals( "extension" ) )
{
ArtifactHandler artifactHandler = artifact.getArtifactHandler();
middle = artifactHandler.getExtension();
}
else
{
middle = "${" + mat.group( 2 ) + "}";
}
}
return left + middle + right;
}
return expression;
}
private List getJarExcludes()
{
List l = new ArrayList( getDefaultExcludes() );
l.add( "META-INF/**" );
return l;
}
private String getOutputDirectory( String output, boolean includeBaseDirectory )
{
if ( output == null )
{
output = "";
}
if ( !output.endsWith( "/" ) && !output.endsWith( "\\" ) )
{
// TODO: shouldn't archiver do this?
output += '/';
}
if ( includeBaseDirectory )
{
if ( output.startsWith( "/" ) )
{
output = finalName + output;
}
else
{
output = finalName + "/" + output;
}
}
else
{
if ( output.startsWith( "/" ) )
{
output = output.substring( 1 );
}
}
return output;
}
private Archiver createArchiver( String format )
throws ArchiverException
{
Archiver archiver;
if ( format.startsWith( "tar" ) )
{
TarArchiver tarArchiver = new TarArchiver();
archiver = tarArchiver;
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 ( compression.equals( "gz" ) )
{
tarCompressionMethod.setValue( "gzip" );
}
else if ( compression.equals( "bz2" ) )
{
tarCompressionMethod.setValue( "bzip2" );
}
else
{
// TODO: better handling
throw new IllegalArgumentException( "Unknown compression format: " + compression );
}
tarArchiver.setCompression( tarCompressionMethod );
}
// TODO: should be able to do this on a file/dir basis
tarArchiver.getOptions().setDirMode( "0700" );
tarArchiver.getOptions().setMode( "0700" );
}
else if ( format.startsWith( "zip" ) )
{
archiver = new ZipArchiver();
}
else if ( format.startsWith( "jar" ) )
{
// TODO: use MavenArchiver for manifest?
JarArchiver jarArchiver = new JarArchiver();
jarArchiver.setCompress( true );
archiver = jarArchiver;
}
else
{
// TODO: better handling
throw new IllegalArgumentException( "Unknown format: " + format );
}
return archiver;
}
public List getDefaultExcludes()
{
List defaultExcludes = new ArrayList();
defaultExcludes.add( "**/*~" );
defaultExcludes.add( "**/#*#" );
defaultExcludes.add( "**/.#*" );
defaultExcludes.add( "**/%*%" );
defaultExcludes.add( "**/._*" );
// CVS
defaultExcludes.add( "**/CVS" );
defaultExcludes.add( "**/CVS/**" );
defaultExcludes.add( "**/.cvsignore" );
// SCCS
defaultExcludes.add( "**/SCCS" );
defaultExcludes.add( "**/SCCS/**" );
// Visual SourceSafe
defaultExcludes.add( "**/vssver.scc" );
// Subversion
defaultExcludes.add( "**/.svn" );
defaultExcludes.add( "**/.svn/**" );
// Mac
defaultExcludes.add( "**/.DS_Store" );
return defaultExcludes;
}
archiver.setDefaultDirectoryMode( Integer.parseInt(
dependencySet.getDirectoryMode(), 8 ) );
archiver.setDefaultFileMode( Integer.parseInt(
dependencySet.getFileMode(), 8 ) );
getLog().debug("DependencySet["+output+"]" +
" dir perms: " + Integer.toString( archiver.getDefaultDirectoryMode(), 8 ) +
" file perms: " + Integer.toString( archiver.getDefaultFileMode(), 8 ) );
AndArtifactFilter filter = new AndArtifactFilter();
filter.add( new ScopeArtifactFilter( dependencySet.getScope() ) );
if ( !dependencySet.getIncludes().isEmpty() )
{
filter.add( new IncludesArtifactFilter( dependencySet.getIncludes() ) );
}
if ( !dependencySet.getExcludes().isEmpty() )
{
filter.add( new ExcludesArtifactFilter( dependencySet.getExcludes() ) );
}
// TODO: includes and excludes
for ( Iterator j = dependencies.iterator(); j.hasNext(); )
{
Artifact artifact = (Artifact) j.next();
if ( filter.include( artifact ) )
{
String name = artifact.getFile().getName();
if ( dependencySet.isUnpack() )
{
// TODO: something like zipfileset in plexus-archiver
// archiver.addJar( )
File tempLocation = new File( workDirectory, name.substring( 0, name.length() - 4 ) );
boolean process = false;
if ( !tempLocation.exists() )
{
tempLocation.mkdirs();
process = true;
}
else if ( artifact.getFile().lastModified() > tempLocation.lastModified() )
{
process = true;
}
if ( process )
{
unpack( artifact.getFile(), tempLocation );
}
archiver.addDirectory( tempLocation, null,
(String[]) getJarExcludes().toArray( EMPTY_STRING_ARRAY ) );
}
else
{
archiver.addFile( artifact.getFile(), output +
evaluateFileNameMapping( dependencySet.getOutputFileNameMapping(), artifact ) );
}
}
}
}
}
private void processFileSets( Archiver archiver, List fileSets, boolean includeBaseDirecetory )
throws ArchiverException
{
for ( Iterator i = fileSets.iterator(); i.hasNext(); )
{
FileSet fileSet = (FileSet) i.next();
String directory = fileSet.getDirectory();
String output = fileSet.getOutputDirectory();
archiver.setDefaultDirectoryMode( Integer.parseInt(
fileSet.getDirectoryMode(), 8 ) );
archiver.setDefaultFileMode( Integer.parseInt(
fileSet.getFileMode(), 8 ) );
getLog().debug("FileSet["+output+"]" +
" dir perms: " + Integer.toString( archiver.getDefaultDirectoryMode(), 8 ) +
" file perms: " + Integer.toString( archiver.getDefaultFileMode(), 8 ) );
if ( directory == null )
{
directory = basedir;
if ( output == null )
{
output = "";
}
}
else
{
if ( output == null )
{
output = directory;
}
}
output = getOutputDirectory( output, includeBaseDirecetory );
String[] includes = (String[]) fileSet.getIncludes().toArray( EMPTY_STRING_ARRAY );
if ( includes.length == 0 )
{
includes = null;
}
List excludesList = fileSet.getExcludes();
excludesList.addAll( getDefaultExcludes() );
String[] excludes = (String[]) excludesList.toArray( EMPTY_STRING_ARRAY );
// TODO: default excludes should be in the archiver?
archiver.addDirectory( new File( directory ), output, includes, excludes );
}
}
private static String evaluateFileNameMapping( String expression, Artifact artifact )
throws MojoExecutionException
{
// this matches the last ${...} string
Pattern pat = Pattern.compile( "^(.*)\\$\\{([^\\}]+)\\}(.*)$" );
Matcher mat = pat.matcher( expression );
String left,right;
Object middle;
if ( mat.matches() )
{
left = evaluateFileNameMapping( mat.group( 1 ), artifact );
try
{
middle = ReflectionValueExtractor.evaluate( "dep." + mat.group( 2 ), artifact );
}
catch (Exception e)
{
throw new MojoExecutionException("Cannot evaluate filenameMapping", e);
}
right = mat.group( 3 );
if ( middle == null )
{
// TODO: There should be a more generic way dealing with that. Having magic words is not good at all.
// probe for magic word
if ( mat.group( 2 ).trim().equals( "extension" ) )
{
ArtifactHandler artifactHandler = artifact.getArtifactHandler();
middle = artifactHandler.getExtension();
}
else
{
middle = "${" + mat.group( 2 ) + "}";
}
}
return left + middle + right;
}
return expression;
}
private static List getJarExcludes()
{
List l = new ArrayList( getDefaultExcludes() );
l.add( "META-INF/**" );
return l;
}
private String getOutputDirectory( String output, boolean includeBaseDirectory )
{
if ( output == null )
{
output = "";
}
if ( !output.endsWith( "/" ) && !output.endsWith( "\\" ) )
{
// TODO: shouldn't archiver do this?
output += '/';
}
if ( includeBaseDirectory )
{
if ( output.startsWith( "/" ) )
{
output = finalName + output;
}
else
{
output = finalName + "/" + output;
}
}
else
{
if ( output.startsWith( "/" ) )
{
output = output.substring( 1 );
}
}
return output;
}
private static Archiver createArchiver( String format )
throws ArchiverException
{
Archiver archiver;
if ( format.startsWith( "tar" ) )
{
TarArchiver tarArchiver = new TarArchiver();
archiver = tarArchiver;
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 ( compression.equals( "gz" ) )
{
tarCompressionMethod.setValue( "gzip" );
}
else if ( compression.equals( "bz2" ) )
{
tarCompressionMethod.setValue( "bzip2" );
}
else
{
// TODO: better handling
throw new IllegalArgumentException( "Unknown compression format: " + compression );
}
tarArchiver.setCompression( tarCompressionMethod );
}
}
else if ( format.startsWith( "zip" ) )
{
archiver = new ZipArchiver();
}
else if ( format.startsWith( "jar" ) )
{
// TODO: use MavenArchiver for manifest?
JarArchiver jarArchiver = new JarArchiver();
jarArchiver.setCompress( true );
archiver = jarArchiver;
}
else
{
// TODO: better handling
throw new IllegalArgumentException( "Unknown format: " + format );
}
return archiver;
}
public static List getDefaultExcludes()
{
List defaultExcludes = new ArrayList();
defaultExcludes.add( "**/*~" );
defaultExcludes.add( "**/#*#" );
defaultExcludes.add( "**/.#*" );
defaultExcludes.add( "**/%*%" );
defaultExcludes.add( "**/._*" );
// CVS
defaultExcludes.add( "**/CVS" );
defaultExcludes.add( "**/CVS/**" );
defaultExcludes.add( "**/.cvsignore" );
// SCCS
defaultExcludes.add( "**/SCCS" );
defaultExcludes.add( "**/SCCS/**" );
// Visual SourceSafe
defaultExcludes.add( "**/vssver.scc" );
// Subversion
defaultExcludes.add( "**/.svn" );
defaultExcludes.add( "**/.svn/**" );
// Mac
defaultExcludes.add( "**/.DS_Store" );
return defaultExcludes;
}
}

View File

@ -1,3 +1,5 @@
<?xml version="1.0"?>
<model>
<id>assembly</id>
<name>Assembly</name>
@ -53,15 +55,9 @@
</fields>
</class>
<class>
<name>FileSet</name>
<name>SetBase</name>
<version>1.0.0</version>
<fields>
<field>
<name>directory</name>
<version>1.0.0</version>
<type>String</type>
<required>true</required>
</field>
<field>
<name>outputDirectory</name>
<version>1.0.0</version>
@ -83,17 +79,38 @@
<multiplicity>*</multiplicity>
</association>
</field>
<field>
<name>fileMode</name>
<version>1.0.0</version>
<type>String</type>
<defaultValue>0644</defaultValue>
</field>
<field>
<name>directoryMode</name>
<version>1.0.0</version>
<type>String</type>
<defaultValue>0755</defaultValue>
</field>
</fields>
</class>
<class>
<name>FileSet</name>
<version>1.0.0</version>
<superClass>SetBase</superClass>
<fields>
<field>
<name>directory</name>
<version>1.0.0</version>
<type>String</type>
<required>true</required>
</field>
</fields>
</class>
<class>
<name>DependencySet</name>
<version>1.0.0</version>
<superClass>SetBase</superClass>
<fields>
<field>
<name>outputDirectory</name>
<version>1.0.0</version>
<type>String</type>
</field>
<field>
<name>outputFileNameMapping</name>
<version>1.0.0</version>
@ -113,20 +130,10 @@
<required>true</required>
</field>
<field>
<name>includes</name>
<name>lineEndings</name>
<version>1.0.0</version>
<association>
<type>String</type>
<multiplicity>*</multiplicity>
</association>
</field>
<field>
<name>excludes</name>
<version>1.0.0</version>
<association>
<type>String</type>
<multiplicity>*</multiplicity>
</association>
<type>String</type>
<!-- native, cr, lf, crlf, ..? -->
</field>
</fields>
</class>