All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.icongmbh.oss.maven.plugin.javassist.JavassistMojo Maven / Gradle / Ivy

Go to download

A maven plugin based on Javassist to manipulate bytecode of project classes at post-compile time.

There is a newer version: 2.0.2
Show newest version
/*
 * Copyright 2012 http://github.com/drochetti/
 *
 * 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.
 */
package de.icongmbh.oss.maven.plugin.javassist;

import static java.lang.Thread.currentThread;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Maven plugin that will apply Javassist
 * class transformations on compiled classes (bytecode instrumentation).
 * 
* Example plugin configuration : * *
 *   <configuration>
 *       <skip>true</skip>
 *       <includeTestClasses>false</includeTestClasses>
 *       <buildDir>bin/classes</buildDir>
 *       <testBuildDir>bin/test-classes</testBuildDir>
 *       <transformerClasses>
 *           <transformerClass>
 *               <className>de.icongmbh.oss.maven.plugin.javassist.SampleTransformer</className>
 *           </transformerClass>
 *       </transformerClasses>
 *   </configuration>
 * 
* @author Daniel Rochetti * @author Uwe Barthel */ @Mojo(name = "javassist", defaultPhase = LifecyclePhase.PROCESS_CLASSES, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME) public class JavassistMojo extends AbstractMojo { private static final Logger logger = LoggerFactory.getLogger(JavassistMojo.class); private static final Class TRANSFORMER_TYPE = ClassTransformer.class; @Parameter(defaultValue = "${project}", property = "javassist.project", required = true, readonly = true) private MavenProject project; /**Skips all processing performed by this goal.*/ @Parameter(defaultValue = "false", property = "javassist.skip", required = false) private boolean skip; @Parameter(defaultValue = "true", property = "javassist.includeTestClasses", required = true) /**Whether or not to include test classes to be processed byt declared transformers.*/ private Boolean includeTestClasses; @Parameter(property = "javassist.transformerClasses", required = true) private ClassTransformerConfiguration[] transformerClasses; /** Allows to customize the build directory of the project, used for both finding classes to transform and outputing them once transformed. * By default, equals to maven's project output directory. Path must be either absolute or relative to project base dir.*/ @Parameter(property = "javassist.buildDir", required = false) private String buildDir; /** Allows to customize the build directory of the tests of the project, used for both finding classes to transform and outputing them once transformed. * By default, equals to maven's project test output directory. Path must be either absolute or relative to project base dir.*/ @Parameter(property = "javassist.testBuildDir", required = false) private String testBuildDir; public void execute() throws MojoExecutionException { if( skip ) { logger.info("Skipping executing."); return; } final JavassistTransformerExecutor executor = new JavassistTransformerExecutor(); try { final List classPath = new ArrayList(); String inputDirectory = buildDir == null ? project.getBuild() .getOutputDirectory() : computeDir(buildDir); String testInputDirectory = testBuildDir == null ? project.getBuild() .getTestOutputDirectory() : computeDir(testBuildDir); final List runtimeClasspathElements = project .getRuntimeClasspathElements(); for (final String runtimeResource : runtimeClasspathElements) { classPath.add(resolveUrl(runtimeResource)); } classPath.add(resolveUrl(inputDirectory)); executor.setAdditionalClassPath(classPath.toArray(new URL[classPath .size()])); executor.setTransformerClasses(instantiateTransformerClasses( currentThread().getContextClassLoader(), transformerClasses)); executor.setInputDirectory(inputDirectory); executor.setOutputDirectory(inputDirectory); executor.execute(); if (includeTestClasses) { classPath.add(resolveUrl(testInputDirectory)); executor.setInputDirectory(testInputDirectory); executor.setOutputDirectory(testInputDirectory); executor.execute(); } } catch (final Exception e) { getLog().error(e.getMessage(), e); throw new MojoExecutionException(e.getMessage(), e); } } private String computeDir(String dir) { File dirFile = new File( dir ); if( dirFile.isAbsolute() ) { return dirFile.getAbsolutePath(); } else { return new File(project.getBasedir(), buildDir).getAbsolutePath(); } } /** * @param contextClassLoader * @param transformerClasses * @return array of passed transformer class name instances * @throws Exception * @see #instantiateTransformerClass(ClassLoader, * ClassTransformerConfiguration) */ protected ClassTransformer[] instantiateTransformerClasses( final ClassLoader contextClassLoader, final ClassTransformerConfiguration... transformerClasses) throws Exception { if (null == transformerClasses || transformerClasses.length <= 0) { throw new MojoExecutionException( "Invalid transformer classes passed"); } final List transformerInstances = new LinkedList(); for (ClassTransformerConfiguration transformerClass : transformerClasses) { final ClassTransformer transformerInstance = instantiateTransformerClass( contextClassLoader, transformerClass); configureTransformerInstance(transformerInstance, transformerClass.getProperties()); transformerInstances.add(transformerInstance); } return transformerInstances .toArray(new ClassTransformer[transformerInstances.size()]); } /** * Instantiate the class passed by {@link ClassTransformerConfiguration} * configuration object. * * @param contextClassLoader * @param transformerClass * @return new instance of passed transformer class name * @throws ClassNotFoundException * @throws NullPointerException * @throws InstantiationException * @throws IllegalAccessException * @throws MojoExecutionException */ protected ClassTransformer instantiateTransformerClass( final ClassLoader contextClassLoader, final ClassTransformerConfiguration transformerClass) throws ClassNotFoundException, NullPointerException, InstantiationException, IllegalAccessException, MojoExecutionException { if (null == transformerClass || null == transformerClass.getClassName() || transformerClass.getClassName().trim().isEmpty()) { throw new MojoExecutionException( "Invalid transformer class name passed"); } final Class transformerClassInstance = Class.forName( transformerClass.getClassName().trim(), true, contextClassLoader); if (TRANSFORMER_TYPE.isAssignableFrom(transformerClassInstance)) { return TRANSFORMER_TYPE .cast(transformerClassInstance.newInstance()); } else { throw new MojoExecutionException( "Transformer class must inherit from " + TRANSFORMER_TYPE.getName()); } } /** * Configure the passed {@link ClassTransformer} instance using the passed * {@link Properties}. * * @param transformerInstance * - maybe null * @param properties * - maybe null or empty * @throws Exception */ protected void configureTransformerInstance( final ClassTransformer transformerInstance, final Properties properties) throws Exception { if (null == transformerInstance) { return; } transformerInstance.configure(properties); } private URL resolveUrl(final String resource) { try { return new File(resource).toURI().toURL(); } catch (final MalformedURLException e) { throw new RuntimeException(e.getMessage(), e); } } public boolean isSkip() { return skip; } public Boolean getIncludeTestClasses() { return includeTestClasses; } public ClassTransformerConfiguration[] getTransformerClasses() { return transformerClasses; } public String getBuildDir() { return buildDir; } public String getTestBuildDir() { return testBuildDir; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy