org.jboss.maven.plugins.retro.WeaveMojo Maven / Gradle / Ivy
package org.jboss.maven.plugins.retro;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.zip.Deflater;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.NameFileFilter;
import org.apache.commons.io.filefilter.TrueFileFilter;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.jboss.weaver.WeaveRunner;
import org.jboss.weaver.Weaver;
/**
* Maven plugin for JBoss Retro Weaver. This can be used to
* do byte code weaving on classes in jars and directories.
* By default the weaver will weave the main classes
* and output the result to a jar with the specified classifier.
*
* @phase process-classes
* @goal weave
*
*/
public class WeaveMojo extends AbstractMojo
{
public static final String JBOSS_RETRO_ARTIFACTID = "jboss-retro";
protected final String fileSep = System.getProperty("file.separator");
protected final String pathSep = System.getProperty("path.separator");
/**
* List of the jar file entries
*/
private ArrayList fileEntries = new ArrayList();
/**
* The Maven Project Object
*
* @parameter expression="${project}"
* @required
* @readonly
*/
protected MavenProject project;
/**
* The Maven Project Helper Object
*
* @component
* @required
* @readonly
*/
protected org.apache.maven.project.MavenProjectHelper projectHelper;
/**
* The plugin dependencies.
*
* @parameter expression="${plugin.artifacts}"
* @required
* @readonly
*/
protected List pluginArtifacts;
/**
* Project classpath.
*
* @parameter expression="${project.compileClasspathElements}"
* @required
* @readonly
*/
protected List classpathElements;
/**
* The directory for compiled classes.
*
* @parameter expression="${project.build.outputDirectory}"
* @required
*/
protected File classesDirectory;
/**
* Include verbose output.
* @parameter
*/
protected boolean verbose = false;
/**
* The Weaver class to use for weaving the classes.
* Defaults to org.jboss.weaver.Weaver
* Any subclass of org.jboss.weaver.Weaver can be used
*
* @parameter
*/
protected String weaverClass = "org.jboss.weaver.Weaver";
/**
* The jar file or directory where the weaved classes
* should be written. The path is relative to the project
* output directory (target).
* Defaults to "target/classes-weaved"
* @parameter
*/
protected String weaverOutputPath;
/**
* Create weaved jar.
* @parameter
*/
protected boolean createJar = true;
/**
* Classifier to append to the weaved output file.
* Defaults to "weaved".
* @parameter
*/
protected String weaveClassifier = "weaved";
/**
* Suppress output information.
* @parameter
*/
protected boolean suppress = true;
/**
* Main plugin execution method
*/
public void execute() throws MojoFailureException
{
this.getLog().info("Weaving classes in: " + this.getClassesDirecotry());
long start = System.currentTimeMillis();
weaveClasses();
long end = System.currentTimeMillis();
this.getLog().info("Weaving complete: " + (end - start) + "ms");
}
protected void weaveClasses() throws MojoFailureException {
// Initialize the WeaveRunner using plugin params
Weaver weaver = createWeaver();
weaver.setClasspath(this.buildClasspath());
weaver.init();
WeaveRunner weaveRunner = new WeaveRunner(weaver);
weaveRunner.setVerbose(verbose);
weaveRunner.setSuppress(suppress);
weaveRunner.setUsingSystemClasspath(false);
weaveRunner.setOutputPath(getOutputPath());
try
{
weaveRunner.addSourcePath(this.getClassesDirecotry().getAbsolutePath());
weaveRunner.weave();
}
catch (Exception e)
{
this.getLog().error(e);
e.printStackTrace();
}
}
/**
* Generates a classpath string based on the compile class path
* and the plugin dependencies.
* @return
*/
protected String buildClasspath() {
StringBuilder classpath = new StringBuilder();
List cpElements = this.getClasspathElements();
for (Object element : cpElements)
{
classpath.append(element);
classpath.append(pathSep);
}
// If the weaver classes can be found in the source directory
// (i.e. we are weaving jboss retro), then we don't want the
// retro jar from the plugin dependency to be pulled in from the repo.
boolean useRetroDep = true;
NameFileFilter nameFilter = new NameFileFilter("Weaver.class");
Collection weaverClassFiles = FileUtils.listFiles(this.getClassesDirecotry(), nameFilter, TrueFileFilter.INSTANCE);
if (weaverClassFiles.size() > 0)
{
useRetroDep = false;
}
for (Object artifactObj : pluginArtifacts)
{
try
{
Artifact artifact = (Artifact) artifactObj;
if (artifact.getFile() != null)
{
if ( useRetroDep || ( ! artifact.getArtifactId().equals(JBOSS_RETRO_ARTIFACTID)))
{
classpath.append(artifact.getFile().getCanonicalPath());
classpath.append(pathSep);
}
}
}
catch (IOException ioe)
{
this.getLog().warn("Could not get filename");
}
}
return classpath.toString();
}
/**
* This method creates the weaver instance. Subclass mojos
* can use this class to override the default weaver configuration.
* @return The weaver instance
*/
protected Weaver createWeaver() throws MojoFailureException {
// We have to set the classpath first because the initialization
// may require access to the classpath.
Weaver weaver = null;
try {
weaver = (Weaver)Class.forName(weaverClass).newInstance();
} catch (Exception e) {
getLog().error("Unable to instantiate weaver class: " + this.weaverClass);
getLog().error(e.getMessage());
throw new MojoFailureException(e.getMessage());
}
return weaver;
}
private void createJarEntries(File retroClassesDir)
{
try
{
this.getLog().info("DEBUG: " + retroClassesDir.getAbsolutePath());
Collection retroClasses = FileUtils.listFiles(retroClassesDir, null, true);
for (Object classFile : retroClasses)
{
String relativePath = classFile.toString().replace(retroClassesDir.getAbsolutePath() + "/", "");
byte[] content = FileUtils.readFileToByteArray((File) classFile);
fileEntries.add(new JarFileEntry(relativePath, content));
}
}
catch (IOException ioe)
{
this.getLog().error("error reading class file: " + ioe);
}
}
private void createRetroJarFile(File retroJarFile)
{
try
{
Manifest manifest = new Manifest();
Attributes attributes = manifest.getMainAttributes();
attributes.putValue("Manifest-Version", "1.0");
attributes.putValue("Created-By", System.getProperty("java.vm.version") + " ("
+ System.getProperty("java.vm.vendor") + ")");
JarOutputStream stream = new JarOutputStream(new FileOutputStream(retroJarFile), manifest);
stream.setLevel(Deflater.BEST_COMPRESSION);
for (JarFileEntry fileEntry : fileEntries)
{
JarEntry jarEntry = new JarEntry(fileEntry.getName());
stream.putNextEntry(jarEntry);
stream.write(fileEntry.getContent());
}
stream.close();
}
catch (IOException ioe)
{
this.getLog().error("Unable to write retro jar: " + ioe);
}
}
protected static class JarFileEntry
{
private byte[] content;
private String name;
public JarFileEntry(String name, byte[] content)
{
this.name = name;
this.content = content;
}
public byte[] getContent()
{
return content;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
}
protected String getOutputPath()
{
if (this.weaverOutputPath == null) {
String classesDirString = getClassesDirecotry().getAbsolutePath();
if(classesDirString.endsWith(this.fileSep)) {
classesDirString = classesDirString.substring(0, (classesDirString.length() - 2));
}
return (classesDirectory + "-" + this.weaveClassifier);
}
else
{
String buildDirectory = project.getBuild().getDirectory();
if (!buildDirectory.endsWith(fileSep)) {
buildDirectory += fileSep;
}
return buildDirectory + this.fileSep + this.weaverOutputPath;
}
}
public List getClasspathElements() {
return this.classpathElements;
}
public File getClassesDirecotry() {
return this.classesDirectory;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy