package org.codehaus.mojo.minijar;
/*
* Copyright 2005 The Apache Software Foundation.
*
* Licensed 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.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.jar.JarOutputStream;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProjectHelper;
import org.codehaus.mojo.minijar.resource.ComponentsXmlHandler;
import org.codehaus.mojo.minijar.resource.LicenseHandler;
import org.vafer.dependency.Clazz;
import org.vafer.dependency.Console;
import org.vafer.dependency.resources.ResourceHandler;
import org.vafer.dependency.resources.Version;
import org.vafer.dependency.utils.Jar;
import org.vafer.dependency.utils.JarUtils;
/**
* Creates an ueberjar including all dependencies into one jar.
*
* @goal ueberjar
* @requiresDependencyResolution compile
* @execute phase="package"
*/
public final class UeberJarMojo
extends AbstractPluginMojo
{
/** @component */
private MavenProjectHelper projectHelper;
/**
* Defines the pattern of the name of final ueber jar.
* Possible substitutions are [artifactId] [version] and [groupId].
*
* @parameter expression="${name}" default-value="[artifactId]-[version]-ueber.jar"
*/
protected String name;
/**
* Defines whether the original artifact should be include so that
* the ueberjar is basically self contained. If set to false the
* ueberjar will only include the dependencies of the project.
*
* @parameter expression="${includeArtifact}" default-value="true"
*/
private boolean includeArtifact;
/**
* By default the new ueberjar gets attached as an additional
* artifact. If you want to replace the orignal artifact set
* this to true.
*
* @parameter expression="${replaceArtifact}" default-value="false"
*/
private boolean replaceArtifact;
private final ResourceHandler[] handlers = {
new LicenseHandler(),
new ComponentsXmlHandler()
};
private InputStream handle( Jar jar, String oldName, String newName, Version[] versions, InputStream inputStream )
throws IOException
{
InputStream is = inputStream;
for (int i = 0; i < handlers.length; i++)
{
if ( is == null )
{
return null;
}
is = handlers[i].onResource( jar, oldName, newName, versions, is );
}
return is;
}
/**
* Creates a combine jar of the dependencies and (as configured) also the build artifact
*
* @param pRemovable Set of classes that can be removed
* @throws MojoExecutionException on error
*/
public void execute( final Set pRemovable, final Set pDependencies, final Set pRelocateDependencies )
throws MojoExecutionException
{
final Set artifacts = new HashSet(pDependencies);
final Artifact projectArtifact = getProject().getArtifact();
if ( includeArtifact )
{
getLog().info( "Including project artifact." );
artifacts.add( projectArtifact );
}
final Jar[] jars = new Jar[ artifacts.size() ];
final Iterator it = artifacts.iterator();
for (int i = 0; i < jars.length; i++)
{
final Artifact artifact = (Artifact) it.next();
final File file = artifact.getFile();
try {
final Jar jar = new Jar( file, artifact != projectArtifact );
jars[i] = jar;
}
catch ( FileNotFoundException e )
{
throw new MojoExecutionException( "Could not locate jar " + file, e );
}
}
final Map variables = new HashMap();
variables.put( "artifactId", projectArtifact.getArtifactId() );
variables.put( "groupId", projectArtifact.getGroupId() );
variables.put( "version", projectArtifact.getVersion() );
final String newName = replaceVariables( variables, name );
final File outputJar = new File( buildDirectory, newName );
try
{
JarUtils.processJars(
jars,
new ResourceHandler() {
public void onStartProcessing( JarOutputStream pOutput )
throws IOException
{
for (int i = 0; i < handlers.length; i++)
{
handlers[i].onStartProcessing( pOutput );
}
}
public void onStartJar( Jar jar, JarOutputStream pOutput )
throws IOException
{
for (int i = 0; i < handlers.length; i++)
{
handlers[i].onStartJar( jar, pOutput );
}
}
public InputStream onResource( Jar jar, String oldName, String newName, Version[] versions, InputStream inputStream )
throws IOException
{
if ( jar != versions[0].getJar() )
{
// only process the first version of it
return null;
}
if ( !oldName.endsWith( ".class" ) )
{
return handle( jar, oldName, newName, versions, inputStream );
}
final String clazzName = oldName.replace( '/' , '.' ).substring( 0, oldName.length() - ".class".length() );
if (pRemovable.contains(new Clazz ( clazzName )))
{
// FIXME: artifact not available
// if (isInKeepUnusedClassesFromArtifacts( artifact ) )
// {
// return handle( jar, oldName, newName, versions, inputStream );
// }
if ( isInKeepUnusedClasses( name ) )
{
return handle( jar, oldName, newName, versions, inputStream );
}
return null;
}
return handle( jar, oldName, newName, versions, inputStream );
}
public void onStopJar( Jar pJar, JarOutputStream pOutput )
throws IOException
{
for (int i = 0; i < handlers.length; i++)
{
handlers[i].onStopJar( pJar, pOutput );
}
}
public void onStopProcessing( JarOutputStream pOutput )
throws IOException
{
for (int i = 0; i < handlers.length; i++)
{
handlers[i].onStopProcessing( pOutput );
}
}
},
new FileOutputStream( outputJar ),
new Console()
{
public void println( String pString )
{
getLog().debug( pString );
}
}
);
}
catch ( Exception e )
{
throw new MojoExecutionException( "Could not create combined output jar " + outputJar, e );
}
if ( replaceArtifact )
{
getLog().info( "Replacing artifact." );
outputJar.renameTo( projectArtifact.getFile() );
}
else
{
getLog().info( "Attaching artifact." );
projectHelper.attachArtifact( getProject(), "jar", "ueber", outputJar );
}
}
}