Giter VIP home page Giter VIP logo

javassist-maven-plugin's People

Contributors

barthel avatar croesch avatar dependabot[bot] avatar drochetti avatar nikelin avatar philipa avatar stephanenicolas avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

javassist-maven-plugin's Issues

fix warnings in javadoc

There any warnings generated by
mvn javadoc:javadoc

Add package-info.java into packages and describe the intention of this package.

Change filter() method to shouldTransform()

Hi there,

I was approached by @stephanenicolas to attempt some sort of interop between the Gradle and Maven plugins. I was wondering if you could turn filter into shouldTransform() instead, as

  • it is more indicative of what the function is
  • does not conflict with gradle/groovy filter function.

Kind Regards,
Daryl

Show generated byte code in Eclipse?

Hey there,
i'm trying to enhance a class with some methods and fields.
For this i have two transformer classes:

<plugin> <groupId>de.icongmbh.oss.maven.plugins</groupId> <artifactId>javassist-maven-plugin</artifactId> <version>1.1.0</version> <configuration> <includeTestClasses>false</includeTestClasses> <transformerClasses> <transformerClass> <className>com.dvag.example.javassist.transformers.PropertyTransformer</className> </transformerClass> <transformerClass> <className>com.dvag.example.javassist.transformers.ToStringTransformer</className> </transformerClass> </transformerClasses> </configuration> <executions> <execution> <phase>process-classes</phase> <goals> <goal>javassist</goal> </goals> </execution> </executions> <dependencies> ... </dependencies> </plugin>

Running my unit - tests with maven ends up as expected, but not when compiling via eclipse..
is it possible to integrate the byte code transformations with eclipse? maybe show generated methods in eclipse outline?

regards,
patrick

Already instrumented class is instrumented again

During a build, a class might be already compiled (if it wasn't modified, it's not compiled again) and already instrumented (transformed), so it's instrumented again. Usually it leads to errors because you might end with an duplicated method or field added before, for example.

  • Solution idea:
    Use Javassist to add a field to the class telling which Transformers were already applied and check for that on each execution.

ClassTransformer not found

The plugin was unable to load my ClassTransformer and a ClassNotFoundException was raised.
I noticed that the classPath variable within the JavassistMojo class contained the correct urls, but these urls were not attached to the currentThread().getContextClassLoader() until after setTransformerClasses was called.

Calling loadAdditionalClassPath(classPath) before executing the code below solves this problem:
executor.setTransformerClasses(instantiateTransformerClasses(
currentThread().getContextClassLoader(), transformerClasses));

How close are we to get the lib on central ?

I would really appreciate to get this library on central. Please, can we shorten the path to go there quickly ?

Is it possible to prune the milestone 1.1 related issues, clean them up and only keep the essential, and to provide an arrival date ?

The only alternative option left is to fork and publish it by myself to get artifacts public.

Store and stamp new generated inner/nested classes

Hi,
I'm generating inner classes so I need to write the new classes to file.
inner.writeFile("./target/classes");
just works but it would be nicer to add a method that could save the class using the build path and mark the new class as processed too.

I can implement the feature for you.

Exception in transformation should stop build

It would be great to stop the build, if the transformation of a class file fails.
This is not possible in the current implementation. In a further step, javassist-maven-plugin could be configured for stopping on exceptions, or not.

For a work around to stop build on exceptions, I have created my own abstract class, which inherits from ClassTransformer. It can be used by extending AbstractClassTransformer instead of ClassTransformer.

package de.icongmbh.oss.maven.plugin.javassist;

import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.Iterator;

import org.apache.maven.MavenExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.LoaderClassPath;
import javassist.NotFoundException;
import javassist.bytecode.ClassFile;

public abstract class AbstractClassTransformer extends ClassTransformer {

private static final Logger LOG = LoggerFactory.getLogger(AbstractClassTransformer.class);

@Override
public void transform(final String inputDir, final String outputDir) {
    if (null == inputDir || inputDir.trim().isEmpty()) {
        return;
    }
    final String outDirectory = outputDir != null
            && !outputDir.trim().isEmpty() ? outputDir : inputDir;
    try {
        transformWithBuildErrors(inputDir, outDirectory,
                iterateClassnames(inputDir));
    } catch (final Exception e) {
        throw new RuntimeException(e);
    }
}

/**
 * Use the passed className iterator, load each one as {@link CtClass},
 * filter the valid candidates (using {@link #filter(CtClass)}) and apply
 * transformation to each one ({@link #applyTransformations(CtClass)}).
 * <ol>
 * <li><strong>Limitation:</strong> do not search inside .jar files yet.</li>
 * <li>This implementation is the same as the original method
 * {@link #transform(String, String, Iterator)} except, that exceptions can
 * be thrown by the called abstract method
 * {@link #applyTransformations(CtClass)} to stop the Maven build, if the
 * transformation fails</li>
 * </ol>
 * 
 * @param inputDir
 *            root directory - required - if <code>null</code> or empty
 *            nothing will be transformed
 * @param outputDir
 *            must be not <code>null</code>
 * @throws Exception
 * @see #applyTransformations(CtClass)
 */
public void transformWithBuildErrors(final String inputDir,
        final String outputDir, final Iterator<String> classNames) throws Exception {
    if (null == classNames || !classNames.hasNext()) {
        return;
    }
    // create new class pool for transform; don't blow up the default
    final ClassPool classPool = new ClassPool(ClassPool.getDefault());
    classPool.childFirstLookup = true;
    classPool.appendClassPath(inputDir);
    classPool.appendClassPath(new LoaderClassPath(Thread
            .currentThread().getContextClassLoader()));
    classPool.appendSystemPath();
    debugClassLoader(classPool);
    int i = 0;
    while (classNames.hasNext()) {
        final String className = classNames.next();
        if (null == className) {
            continue;
        }
        try {
            LOG.debug("Got class name {}", className);
            classPool.importPackage(className);
            final CtClass candidateClass = classPool.get(className);
            initializeClass(candidateClass);
            if (!hasStamp(candidateClass)
                    && shouldTransform(candidateClass)) {
                applyTransformations(candidateClass);
                applyStamp(candidateClass);
                candidateClass.writeFile(outputDir);
                LOG.debug("Class {} instrumented by {}", className,
                        getClass().getName());
                ++i;
            }
        } catch (final NotFoundException e) {
            throw new MavenExecutionException(String.format("Class %s has not been found on class path.", className), e);
        } catch (final Exception ex) {
            throw new MavenExecutionException(String.format("Instrumenting class %s failed.", className), ex);
        }
    }
    LOG.info("#{} classes instrumented by {}", i, getClass()
            .getName());
}

private void initializeClass(final CtClass candidateClass)
        throws NotFoundException {
    debugClassFile(candidateClass.getClassFile2());
    // TODO hack to initialize class to avoid further NotFoundException
    // (what's the right way of doing this?)
    candidateClass.subtypeOf(ClassPool.getDefault().get(
            Object.class.getName()));
}

private void debugClassLoader(final ClassPool classPool) {
    if (!LOG.isDebugEnabled()) {
        return;
    }
    LOG.debug(" - classPool: {}", classPool.toString());
    ClassLoader classLoader = classPool.getClassLoader();
    while (classLoader != null) {
        LOG.debug(" -- {}: {}", classLoader.getClass().getName(),
                classLoader.toString());
        if (classLoader instanceof URLClassLoader) {
            LOG.debug(" --- urls: {}", Arrays
                    .deepToString(((URLClassLoader) classLoader).getURLs()));
        }
        classLoader = classLoader.getParent();
    }
}

private void debugClassFile(final ClassFile classFile) {
    if (!LOG.isDebugEnabled()) {
        return;
    }
    LOG.debug(" - class: {}", classFile.getName());
    LOG.debug(" -- Java version: {}.{}", classFile.getMajorVersion(),
            classFile.getMinorVersion());
    LOG.debug(" -- interface: {} abstract: {} final: {}",
            classFile.isInterface(), classFile.isAbstract(),
            classFile.isFinal());
    LOG.debug(" -- extends class: {}", classFile.getSuperclass());
    LOG.debug(" -- implements interfaces: {}",
            Arrays.deepToString(classFile.getInterfaces()));
}

}

All interactions with ClassTransformer should use modified context classloader

The context classloader is adjusted to add the input directory the local build output directory and the dependencies before calling the transformation methods.

I think the context classloader should be set around all interactions with the ClassTransformer. This would allow configure() to access classes in the local project, and also allow the ClassTransformer implementations to be loaded from the local project.

If you agree, I'm happy to do the work. I'd pull the context classloader management up from JavassistTransformerExecutor.execute() to JavassistMojo.execute().

Would it work on Android ?

Hi @drochetti,

do you think it would be easy to use an alternative implementation on javassist with your plugin ?

I would like to make it work on Android and it looks like someone already has a github project to make javassist compatible with Android :
https://github.com/crimsonwoods/javassist-android

The plugin is really nice, a little more documentation and a release on central would be nice.

Stéphane

change package names

Change the package names before/after the first release.

[...]
As I've been very busy, I think a transfer will work best for you, so you'll don't need
to wait for pull request merges anymore. You're free to change package name too,
since is using my GitHub username on it (lack of inspiration at the time).
I'll be happy to see this project improved and to fork it to contribute anytime.

Cheers!
Daniel (@drochetti)

On Tue, Mar 11, 2014 at 12:48 PM, @barthel wrote:

Hi Barthel! Thanks for your contact.
I've been super busy with other projects and I would love to have you
guys maintaing this plugin, that helped me a lot once.

I'll be happy to transfer the repository to you guys if you want, just
let me know to which user should I transfer.

Cheers!

Daniel (@drochetti)

The version of the Java compiler must be considered when the classes are created by javassist.

The major version number of class files created from scratch. The default value is 47 (JDK 1.3).

javassist.bytecode.ClassFile#MAJOR_VERSION

The major version numbers of class files for JDK 1.1 - 1.8

javassist.bytecode.ClassFile#JAVA_1
javassist.bytecode.ClassFile#JAVA_2
javassist.bytecode.ClassFile#JAVA_3
javassist.bytecode.ClassFile#JAVA_4
javassist.bytecode.ClassFile#JAVA_5
javassist.bytecode.ClassFile#JAVA_6
javassist.bytecode.ClassFile#JAVA_7
javassist.bytecode.ClassFile#JAVA_8

Uniform API with Gradle plugin

Hi @barthel and @darylteo,

would you agree to define a simple common java interface for ClassTransformers, it is already the case de facto, but a real common interface would be cleaner and it could be provided inside a simple jar artifact on maven central.

If you agree, I suggest that I host the project on GH and add you 2 as full contributors for the repo and on maven central.

It could be as simple as :

public interface ClassTransformer {
  void applyTransformations(CtClass classToTransform);
  boolean shouldTransform(final CtClass candidateClass)
;
}

On gradle repo, same issue :
darylteo/gradle-plugins#4

update pom

Add/modify information within pom:

  • Java version for compile (1.6)
  • scm (github)
  • ci (travis-ci.org)
  • issueManagement (github)
  • licenses (APL 2.0)
  • developers
  • ...

Don't break build if configured directory isn't available

To prevent something like:

[ERROR] Parameter 'directory' is not a directory
java.lang.IllegalArgumentException: Parameter 'directory' is not a directory
    at org.apache.commons.io.FileUtils.validateListFilesParameters(FileUtils.java:545)
    at org.apache.commons.io.FileUtils.listFiles(FileUtils.java:521)
    at org.apache.commons.io.FileUtils.iterateFiles(FileUtils.java:628)
    at de.icongmbh.oss.maven.plugin.javassist.ClassTransformer.iterateClassnames(ClassTransformer.java:198)
    at de.icongmbh.oss.maven.plugin.javassist.ClassTransformer.transform(ClassTransformer.java:131)
    at de.icongmbh.oss.maven.plugin.javassist.JavassistTransformerExecutor.execute(JavassistTransformerExecutor.java:107)
    at de.icongmbh.oss.maven.plugin.javassist.JavassistTransformerExecutor.execute(JavassistTransformerExecutor.java:98)
    at de.icongmbh.oss.maven.plugin.javassist.JavassistMojo.execute(JavassistMojo.java:118)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:106)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:317)
    at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:152)
    at org.jvnet.hudson.maven3.launcher.Maven31Launcher.main(Maven31Launcher.java:132)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchStandard(Launcher.java:330)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:238)
    at jenkins.maven3.agent.Maven31Main.launch(Maven31Main.java:181)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at hudson.maven.Maven3Builder.call(Maven3Builder.java:134)
    at hudson.maven.Maven3Builder.call(Maven3Builder.java:69)
    at hudson.remoting.UserRequest.perform(UserRequest.java:118)
    at hudson.remoting.UserRequest.perform(UserRequest.java:48)
    at hudson.remoting.Request$2.run(Request.java:328)
    at hudson.remoting.InterceptingExecutorService$1.call(InterceptingExecutorService.java:72)
    at java.util.concurrent.FutureTask.run(FutureTask.java:262)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------

For example in maven assembly projects where no target/classes (buildDir) exists and the plugin is defined in parent POM.

reduce visibility of internal stampField

    if (!classToTransform.isInterface()) {
      stampField.setModifiers(AccessFlag.PRIVATE | AccessFlag.STATIC | AccessFlag.FINAL);
    } else {
      stampField.setModifiers(AccessFlag.PUBLIC | AccessFlag.STATIC | AccessFlag.FINAL);
    }
    classToTransform.addField(stampField, Initializer.constant(true));

maven site

Add and configure maven site and provide via gh-pages.

Only one transformer transforms class when using input as output directory

Using the master version of the repository one can only apply one transformer.

This seems to be introduced by 1edfc58 because now the stamp field's name is __TRANSFORMED_BY_JAVASSIST_MAVEN_PLUGIN__de_icongmbh_oss_maven_plugin_javassist_JavassistTransformerExecutor for all transformers.

Suggested fix is to not use the JavassistTransformerExecutor's class name as suffix but the class of the transformer.

Versions dependencies conflicts

I'm using enforcer-plugin and it detects followings version conflicts, regarding :

<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>

and

<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-classworlds</artifactId>

How come did you push a release into maven central without checking version conflicts ??

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.