diff --git a/README.md b/README.md index b6fba90..594ee00 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -[![Maven Central](https://img.shields.io/maven-central/v/net.tascalate.javaflow/net.tascalate.javaflow.parent.svg)](https://search.maven.org/artifact/net.tascalate.javaflow/net.tascalate.javaflow.parent/2.7.0/pom) [![GitHub release](https://img.shields.io/github/release/vsilaev/tascalate-javaflow.svg)](https://github.com/vsilaev/tascalate-javaflow/releases/tag/2.7.0) [![license](https://img.shields.io/github/license/vsilaev/tascalate-javaflow.svg)](http://www.apache.org/licenses/LICENSE-2.0.txt) +[![Maven Central](https://img.shields.io/maven-central/v/net.tascalate.javaflow/net.tascalate.javaflow.parent.svg)](https://search.maven.org/artifact/net.tascalate.javaflow/net.tascalate.javaflow.parent/2.7.1/pom) [![GitHub release](https://img.shields.io/github/release/vsilaev/tascalate-javaflow.svg)](https://github.com/vsilaev/tascalate-javaflow/releases/tag/2.7.1) [![license](https://img.shields.io/github/license/vsilaev/tascalate-javaflow.svg)](http://www.apache.org/licenses/LICENSE-2.0.txt) -# IMPORTANT NOTICE FOR RELEASE 2.7.0!!! +# IMPORTANT NOTICE FOR RELEASE 2.7.1!!! - Agents & Tools projects were refactored to follow consisntent naming of classes and to avoid package name clashes - Separate provider was extracted from `CdiProxy` to allow reuse in mutliple scenarious (not only in Java Agent) - `net.tascalate.javaflow.provider.asm[VERSION]` artifacts are deprecated now and scheduled for removal in next release @@ -34,7 +34,7 @@ You have to add the following configuration to enable build-time instrumentation net.tascalate.javaflow net.tascalate.javaflow.api - 2.7.0 + 2.7.1 @@ -59,7 +59,7 @@ You have to add the following configuration to enable build-time instrumentation net.tascalate.javaflow net.tascalate.javaflow.tools.maven - 2.7.0 + 2.7.1 process-classes @@ -72,7 +72,7 @@ You have to add the following configuration to enable build-time instrumentation ``` -Note that if you are using continuations with Java 1.8 lambdas then you need to add [Tascalate JavaFlow instrumentation agent](https://github.com/vsilaev/tascalate-javaflow/releases/download/2.7.0/javaflow.instrument-continuations.jar) at run-time as command-line option, while lambda-related classes are generated by JVM on the fly and there is no other way to instrument them. If this is not an option, then you can de-sugar all lambdas with [RetroLambda](https://github.com/luontola/retrolambda) Maven plugin at build-time (RetroLambda output is supported by Tascalate JavaFlow 2.3.2 or higher). +Note that if you are using continuations with Java 1.8 lambdas then you need to add [Tascalate JavaFlow instrumentation agent](https://github.com/vsilaev/tascalate-javaflow/releases/download/2.7.1/javaflow.instrument-continuations.jar) at run-time as command-line option, while lambda-related classes are generated by JVM on the fly and there is no other way to instrument them. If this is not an option, then you can de-sugar all lambdas with [RetroLambda](https://github.com/luontola/retrolambda) Maven plugin at build-time (RetroLambda output is supported by Tascalate JavaFlow 2.3.2 or higher). Please refer to [pom.xml](https://github.com/vsilaev/tascalate-javaflow-examples/blob/master/net.tascalate.javaflow.examples.common/pom.xml) in examples project for typical Maven configuration @@ -101,7 +101,7 @@ It's possibe to instrument compiled Java classes as below: You may download a complete [examples project setup](https://github.com/vsilaev/tascalate-javaflow-examples/releases/download/1.0.10/tascalate-javaflow-ant-project-setup1.zip) from [the latest release](https://github.com/vsilaev/tascalate-javaflow-examples/releases/tag/1.0.10) for complete configuration template. Please pay attention to ant-lib folder with Ant TaskDef and lib folders with compile-/runtime-dependencies. # Java Instrumentation Agent (Runt-time Instrumentation) -As an alternative to compile-time bytecode instrumentation, you MAY use [Tascalate JavaFlow Instrumentation Agent](https://github.com/vsilaev/tascalate-javaflow/releases/download/2.7.0/javaflow.instrument-continuations.jar) from [the latest release](https://github.com/vsilaev/tascalate-javaflow/releases/tag/2.7.0) to enable continuations support at class-loading time. Please note, that if you are using Java 8 and creating continuable lambda functions (either anonymous or/and as method references), and you don't replace them with tools like [RetroLambda](https://github.com/luontola/retrolambda) as mentioned above, then you SHOULD use this instrumentation agent always: as long as Java run-time generates implementation of functional interfaces on the fly there is no other option to instrument them. To enable Tascalate JavaFlow Instrumentation Agent please add the following arguments to Java command line: +As an alternative to compile-time bytecode instrumentation, you MAY use [Tascalate JavaFlow Instrumentation Agent](https://github.com/vsilaev/tascalate-javaflow/releases/download/2.7.1/javaflow.instrument-continuations.jar) from [the latest release](https://github.com/vsilaev/tascalate-javaflow/releases/tag/2.7.1) to enable continuations support at class-loading time. Please note, that if you are using Java 8 and creating continuable lambda functions (either anonymous or/and as method references), and you don't replace them with tools like [RetroLambda](https://github.com/luontola/retrolambda) as mentioned above, then you SHOULD use this instrumentation agent always: as long as Java run-time generates implementation of functional interfaces on the fly there is no other option to instrument them. To enable Tascalate JavaFlow Instrumentation Agent please add the following arguments to Java command line: ```bash java -javaagent:/javaflow.instrument-continuations.jar ``` @@ -110,7 +110,7 @@ The agent JAR file includes all necessary dependencies and requires no additiona Another useful application of the instrumentation agent is to apply it for debugging code within your IDE of choice. Just specify the "-javaagent" option listed above in your IDE debug/run configuration and you will be able to perform quick "debug-fix" loops without executing full project rebuild. # Command-line tools -It's possible to use a stand-alone command-line utility [JavaFlowRewriteJar.jar](https://github.com/vsilaev/tascalate-javaflow/releases/download/2.7.0/JavaFlowRewriteJar.jar) to instrument JAR archives containing continuable classes. Please use the following command: +It's possible to use a stand-alone command-line utility [JavaFlowRewriteJar.jar](https://github.com/vsilaev/tascalate-javaflow/releases/download/2.7.1/JavaFlowRewriteJar.jar) to instrument JAR archives containing continuable classes. Please use the following command: ```bash java -jar JavaFlowRewriteJar.jar src1.jar dst1.jar src2.jar dst2.jar... @@ -118,7 +118,7 @@ It's possible to use a stand-alone command-line utility [JavaFlowRewriteJar.jar] Note, that the source and the destination should be different files. # CDI Support -To work correctly in CDI environment continuable methods should be advised only by continuation-aware CDI proxies (interceptors, scope proxies, etc). Obviously, generation of these proxies is out of our control. Plus, major CDI containers (JBoss Weld and Apache OpenWebBeans) generates such proxies dynamically at run-time. Therefore if you plan to use Tascalate JavaFlow continuations with managed beans' methods then it's necessary to instrument CDI-specific proxies with [javaflow.instrument-proxies.jar](https://github.com/vsilaev/tascalate-javaflow/releases/download/2.7.0/javaflow.instrument-proxies.jar) Java Agent: +To work correctly in CDI environment continuable methods should be advised only by continuation-aware CDI proxies (interceptors, scope proxies, etc). Obviously, generation of these proxies is out of our control. Plus, major CDI containers (JBoss Weld and Apache OpenWebBeans) generates such proxies dynamically at run-time. Therefore if you plan to use Tascalate JavaFlow continuations with managed beans' methods then it's necessary to instrument CDI-specific proxies with [javaflow.instrument-proxies.jar](https://github.com/vsilaev/tascalate-javaflow/releases/download/2.7.1/javaflow.instrument-proxies.jar) Java Agent: ```bash java -javaagent:/javaflow.instrument-proxies.jar ``` diff --git a/net.tascalate.javaflow.agent.common/pom.xml b/net.tascalate.javaflow.agent.common/pom.xml index 45757cc..28b7a81 100644 --- a/net.tascalate.javaflow.agent.common/pom.xml +++ b/net.tascalate.javaflow.agent.common/pom.xml @@ -4,7 +4,7 @@ net.tascalate.javaflow net.tascalate.javaflow.parent - 2.7.0 + 2.7.1 ../ diff --git a/net.tascalate.javaflow.agent.core/pom.xml b/net.tascalate.javaflow.agent.core/pom.xml index 70dfe25..3c9f868 100644 --- a/net.tascalate.javaflow.agent.core/pom.xml +++ b/net.tascalate.javaflow.agent.core/pom.xml @@ -4,7 +4,7 @@ net.tascalate.javaflow net.tascalate.javaflow.parent - 2.7.0 + 2.7.1 ../ diff --git a/net.tascalate.javaflow.agent.proxy/pom.xml b/net.tascalate.javaflow.agent.proxy/pom.xml index 775bd77..3d9904a 100644 --- a/net.tascalate.javaflow.agent.proxy/pom.xml +++ b/net.tascalate.javaflow.agent.proxy/pom.xml @@ -4,7 +4,7 @@ net.tascalate.javaflow net.tascalate.javaflow.parent - 2.7.0 + 2.7.1 ../ diff --git a/net.tascalate.javaflow.api/pom.xml b/net.tascalate.javaflow.api/pom.xml index d7c0027..34a593f 100644 --- a/net.tascalate.javaflow.api/pom.xml +++ b/net.tascalate.javaflow.api/pom.xml @@ -4,7 +4,7 @@ net.tascalate.javaflow net.tascalate.javaflow.parent - 2.7.0 + 2.7.1 ../ diff --git a/net.tascalate.javaflow.providers.asm3/pom.xml b/net.tascalate.javaflow.providers.asm3/pom.xml index 83b87a2..f923cb3 100644 --- a/net.tascalate.javaflow.providers.asm3/pom.xml +++ b/net.tascalate.javaflow.providers.asm3/pom.xml @@ -4,7 +4,7 @@ net.tascalate.javaflow net.tascalate.javaflow.parent - 2.7.0 + 2.7.1 ../ diff --git a/net.tascalate.javaflow.providers.asm4/pom.xml b/net.tascalate.javaflow.providers.asm4/pom.xml index 1e58be1..407f09c 100644 --- a/net.tascalate.javaflow.providers.asm4/pom.xml +++ b/net.tascalate.javaflow.providers.asm4/pom.xml @@ -4,7 +4,7 @@ net.tascalate.javaflow net.tascalate.javaflow.parent - 2.7.0 + 2.7.1 ../ diff --git a/net.tascalate.javaflow.providers.asm5/pom.xml b/net.tascalate.javaflow.providers.asm5/pom.xml index 471861f..fbad08e 100644 --- a/net.tascalate.javaflow.providers.asm5/pom.xml +++ b/net.tascalate.javaflow.providers.asm5/pom.xml @@ -4,7 +4,7 @@ net.tascalate.javaflow net.tascalate.javaflow.parent - 2.7.0 + 2.7.1 ../ diff --git a/net.tascalate.javaflow.providers.asmx/pom.xml b/net.tascalate.javaflow.providers.asmx/pom.xml index 06e64b8..7cae40a 100644 --- a/net.tascalate.javaflow.providers.asmx/pom.xml +++ b/net.tascalate.javaflow.providers.asmx/pom.xml @@ -4,7 +4,7 @@ net.tascalate.javaflow net.tascalate.javaflow.parent - 2.7.0 + 2.7.1 ../ diff --git a/net.tascalate.javaflow.providers.core/pom.xml b/net.tascalate.javaflow.providers.core/pom.xml index 3e85f14..66f4812 100644 --- a/net.tascalate.javaflow.providers.core/pom.xml +++ b/net.tascalate.javaflow.providers.core/pom.xml @@ -4,7 +4,7 @@ net.tascalate.javaflow net.tascalate.javaflow.parent - 2.7.0 + 2.7.1 ../ diff --git a/net.tascalate.javaflow.providers.proxy/pom.xml b/net.tascalate.javaflow.providers.proxy/pom.xml index bc1d429..35e685c 100644 --- a/net.tascalate.javaflow.providers.proxy/pom.xml +++ b/net.tascalate.javaflow.providers.proxy/pom.xml @@ -4,7 +4,7 @@ net.tascalate.javaflow net.tascalate.javaflow.parent - 2.7.0 + 2.7.1 ../ diff --git a/net.tascalate.javaflow.spi/pom.xml b/net.tascalate.javaflow.spi/pom.xml index 2fa39fc..c75b9be 100644 --- a/net.tascalate.javaflow.spi/pom.xml +++ b/net.tascalate.javaflow.spi/pom.xml @@ -4,7 +4,7 @@ net.tascalate.javaflow net.tascalate.javaflow.parent - 2.7.0 + 2.7.1 ../ diff --git a/net.tascalate.javaflow.tools.ant/pom.xml b/net.tascalate.javaflow.tools.ant/pom.xml index 20d7ad8..ab49bd4 100644 --- a/net.tascalate.javaflow.tools.ant/pom.xml +++ b/net.tascalate.javaflow.tools.ant/pom.xml @@ -4,7 +4,7 @@ net.tascalate.javaflow net.tascalate.javaflow.parent - 2.7.0 + 2.7.1 ../ diff --git a/net.tascalate.javaflow.tools.jar/pom.xml b/net.tascalate.javaflow.tools.jar/pom.xml index 0dd58e8..35161fe 100644 --- a/net.tascalate.javaflow.tools.jar/pom.xml +++ b/net.tascalate.javaflow.tools.jar/pom.xml @@ -4,7 +4,7 @@ net.tascalate.javaflow net.tascalate.javaflow.parent - 2.7.0 + 2.7.1 ../ diff --git a/net.tascalate.javaflow.tools.maven/pom.xml b/net.tascalate.javaflow.tools.maven/pom.xml index 462ebc8..d1a3179 100644 --- a/net.tascalate.javaflow.tools.maven/pom.xml +++ b/net.tascalate.javaflow.tools.maven/pom.xml @@ -4,7 +4,7 @@ net.tascalate.javaflow net.tascalate.javaflow.parent - 2.7.0 + 2.7.1 ../ diff --git a/net.tascalate.javaflow.tools.maven/src/main/java/org/apache/commons/javaflow/tools/maven/ContinuableClassesInstrumentationMojo.java b/net.tascalate.javaflow.tools.maven/src/main/java/org/apache/commons/javaflow/tools/maven/ContinuableClassesInstrumentationMojo.java index 596d77e..967707e 100644 --- a/net.tascalate.javaflow.tools.maven/src/main/java/org/apache/commons/javaflow/tools/maven/ContinuableClassesInstrumentationMojo.java +++ b/net.tascalate.javaflow.tools.maven/src/main/java/org/apache/commons/javaflow/tools/maven/ContinuableClassesInstrumentationMojo.java @@ -18,15 +18,17 @@ import static java.lang.Thread.currentThread; import java.io.File; +import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; -import java.net.URLClassLoader; import java.util.ArrayList; import java.util.List; import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecution; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.logging.Log; +import org.apache.maven.plugins.annotations.Component; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; @@ -53,7 +55,7 @@ * * */ -@Mojo(name = "javaflow-enhance", defaultPhase = LifecyclePhase.PROCESS_CLASSES, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME) +@Mojo(name = "javaflow-enhance", defaultPhase = LifecyclePhase.PROCESS_CLASSES, requiresDependencyResolution = ResolutionScope.TEST /* ALL DEPENDENCIES */) public class ContinuableClassesInstrumentationMojo extends AbstractMojo { @Parameter(defaultValue = "${project}", property = "javaflow.enhancer.project", required = true, readonly = true) @@ -85,6 +87,9 @@ public class ContinuableClassesInstrumentationMojo extends AbstractMojo { @Parameter(property = "javaflow.enhancer.testBuildDir", required = false) private String testBuildDir; + @Component + private MojoExecution execution; + public void execute() throws MojoExecutionException { final Log log = getLog(); if (skip) { @@ -92,26 +97,49 @@ public void execute() throws MojoExecutionException { return; } - ClassLoader originalContextClassLoader = currentThread().getContextClassLoader(); - try { - List classPath = new ArrayList(); - - for (String runtimeResource : project.getRuntimeClasspathElements()) { - classPath.add(resolveUrl(new File(runtimeResource))); - } - - File inputDirectory = buildDir == null + File mainInputDirectory = buildDir == null ? new File(project.getBuild().getOutputDirectory()) : computeDir(buildDir); + + if (mainInputDirectory.exists()) { + // Use runtime instead of compile - runtime contains non less than compile + transformFiles(mainInputDirectory, project.getRuntimeClasspathElements()); + } else { + log.warn("No main build output directory available, skipping enhancing main classes"); + } - classPath.add(resolveUrl(inputDirectory)); + if (includeTestClasses) { + File testInputDirectory = testBuildDir == null + ? new File(project.getBuild().getTestOutputDirectory()) + : computeDir(testBuildDir); - loadAdditionalClassPath(classPath); + if (testInputDirectory.exists()) { + transformFiles(testInputDirectory, project.getTestClasspathElements()); + } else if ("process-test-classes".equals(execution.getLifecyclePhase())) { + log.warn("No test build output directory available, skipping enhancing test classes"); + } + } + } catch (Exception e) { + getLog().error(e.getMessage(), e); + throw new MojoExecutionException(e.getMessage(), e); + } + } + + private void transformFiles(File inputDirectory, List classPathEntries) throws IOException { + final Log log = getLog(); + ClassLoader originalContextClassLoader = currentThread().getContextClassLoader(); + try { + List classPath = new ArrayList(); + for (String classPathEntry : classPathEntries) { + classPath.add(resolveUrl(new File(classPathEntry))); + } + classPath.add(resolveUrl(inputDirectory)); ResourceTransformer dirTransformer = RewritingUtils.createTransformer( classPath.toArray(new URL[] {}) ); + try { long now = System.currentTimeMillis(); @@ -124,47 +152,14 @@ public void execute() throws MojoExecutionException { } } } - - if (includeTestClasses) { - File testInputDirectory = testBuildDir == null - ? new File(project.getBuild().getTestOutputDirectory()) - : computeDir(testBuildDir); - - if (testInputDirectory.exists()) { - for (File source : RecursiveFilesIterator.scanClassFiles(testInputDirectory)) { - if (source.lastModified() <= now) { - log.debug("Applying continuations support: " + source); - boolean rewritten = RewritingUtils.rewriteClassFile(source, dirTransformer, source); - if (rewritten) { - log.info("Rewritten continuation-enabled class file: " + source); - } - - } - } - } - } } finally { dirTransformer.release(); } - } catch (Exception e) { - getLog().error(e.getMessage(), e); - throw new MojoExecutionException(e.getMessage(), e); + } finally { currentThread().setContextClassLoader(originalContextClassLoader); } - } - - private void loadAdditionalClassPath(List classPath) { - if (classPath.isEmpty()) { - return; - } - ClassLoader contextClassLoader = currentThread().getContextClassLoader(); - - URLClassLoader pluginClassLoader = URLClassLoader.newInstance( - classPath.toArray(new URL[classPath.size()]), contextClassLoader - ); - - currentThread().setContextClassLoader(pluginClassLoader); + } private File computeDir(String dir) { diff --git a/net.tascalate.javaflow.tools.runtime/pom.xml b/net.tascalate.javaflow.tools.runtime/pom.xml index 281ce90..a7b4e64 100644 --- a/net.tascalate.javaflow.tools.runtime/pom.xml +++ b/net.tascalate.javaflow.tools.runtime/pom.xml @@ -4,7 +4,7 @@ net.tascalate.javaflow net.tascalate.javaflow.parent - 2.7.0 + 2.7.1 ../ diff --git a/pom.xml b/pom.xml index 18e5a4b..c31c6d4 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ net.tascalate.javaflow net.tascalate.javaflow.parent - 2.7.0 + 2.7.1 pom Tascalate JavFlow