You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by db...@apache.org on 2020/06/12 04:01:25 UTC

[tomee-patch-plugin] branch master updated (2a06d9f -> ec32c94)

This is an automated email from the ASF dual-hosted git repository.

dblevins pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/tomee-patch-plugin.git.


    from 2a06d9f  Initial code forked from https://github.com/tomitribe/jkta
     new ebe5dad  Rough compilation capabilities lifted from maven-compile-plugin
     new c58fe32  Build a compile-time classpath from the zips being patched
     new b8f5475  Remove fields not used
     new ec32c94  Very nearly functional jar-patching

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../{AnnotationTransformer.java => Clazz.java}     |  38 +-
 .../main/java/org/apache/tomee/patch/core/Log.java |  35 ++
 .../java/org/apache/tomee/patch/core/NullLog.java  |  99 +++++
 .../apache/tomee/patch/core/Transformation.java    | 128 +++++-
 tomee-patch-plugin/pom.xml                         |  49 ++-
 .../patch/plugin/CompilationFailureException.java  |  85 ++++
 .../org/apache/tomee/patch/plugin/MavenLog.java    |  76 ++++
 .../org/apache/tomee/patch/plugin/PatchMojo.java   | 430 +++++++++++++++++++++
 .../apache/tomee/patch/plugin/TransformMojo.java   |  33 --
 9 files changed, 925 insertions(+), 48 deletions(-)
 copy tomee-patch-core/src/main/java/org/apache/tomee/patch/core/{AnnotationTransformer.java => Clazz.java} (53%)
 create mode 100644 tomee-patch-core/src/main/java/org/apache/tomee/patch/core/Log.java
 create mode 100644 tomee-patch-core/src/main/java/org/apache/tomee/patch/core/NullLog.java
 create mode 100644 tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/CompilationFailureException.java
 create mode 100644 tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/MavenLog.java
 create mode 100644 tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/PatchMojo.java
 delete mode 100644 tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/TransformMojo.java


[tomee-patch-plugin] 03/04: Remove fields not used

Posted by db...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dblevins pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tomee-patch-plugin.git

commit b8f5475fdf6f47dc3463d2f2601f9ed78e3f7abc
Author: David Blevins <da...@gmail.com>
AuthorDate: Thu Jun 11 19:33:58 2020 -0700

    Remove fields not used
---
 .../java/org/apache/tomee/patch/plugin/PatchMojo.java    | 16 ++--------------
 1 file changed, 2 insertions(+), 14 deletions(-)

diff --git a/tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/PatchMojo.java b/tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/PatchMojo.java
index ef995d4..bcf8ab8 100644
--- a/tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/PatchMojo.java
+++ b/tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/PatchMojo.java
@@ -64,9 +64,6 @@ public class PatchMojo extends AbstractMojo {
     @Parameter(defaultValue = "${session}", readonly = true, required = true)
     private MavenSession session;
 
-    @Parameter(defaultValue = "${project.build.directory}", required = true)
-    private File outputDirectory;
-
     @Parameter(defaultValue = "${project.basedir}/src/patch/java", required = true)
     private File patchSourceDirectory;
 
@@ -89,13 +86,13 @@ public class PatchMojo extends AbstractMojo {
     private Map<String, String> jdkToolchain;
 
     /**
-     * Sets the executable of the compiler to use when {@link #fork} is <code>true</code>.
+     * Sets the executable of the compiler to use when fork is <code>true</code>.
      */
     @Parameter(property = "maven.compiler.executable")
     private String executable;
 
     /**
-     * Version of the compiler to use, ex. "1.3", "1.5", if {@link #fork} is set to <code>true</code>.
+     * Version of the compiler to use, ex. "1.3", "1.5", if fork is set to <code>true</code>.
      */
     @Parameter(property = "maven.compiler.compilerVersion")
     private String compilerVersion;
@@ -127,15 +124,6 @@ public class PatchMojo extends AbstractMojo {
     @Parameter(property = "encoding", defaultValue = "${project.build.sourceEncoding}")
     private String encoding;
 
-    @Component
-    private MavenProjectHelper projectHelper;
-
-    @Component
-    protected ArtifactFactory factory;
-
-    @Component
-    protected ArtifactResolver resolver;
-
     /**
      * Plexus compiler manager.
      */


[tomee-patch-plugin] 04/04: Very nearly functional jar-patching

Posted by db...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dblevins pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tomee-patch-plugin.git

commit ec32c94ae0035b44d941e43a3732bd53a182bedb
Author: David Blevins <da...@gmail.com>
AuthorDate: Thu Jun 11 21:00:58 2020 -0700

    Very nearly functional jar-patching
---
 .../java/org/apache/tomee/patch/core/Clazz.java    |  57 +++++++++
 .../main/java/org/apache/tomee/patch/core/Log.java |  35 ++++++
 .../java/org/apache/tomee/patch/core/NullLog.java  |  99 ++++++++++++++++
 .../apache/tomee/patch/core/Transformation.java    | 128 ++++++++++++++++++++-
 .../org/apache/tomee/patch/plugin/MavenLog.java    |  76 ++++++++++++
 .../org/apache/tomee/patch/plugin/PatchMojo.java   |  26 ++++-
 6 files changed, 412 insertions(+), 9 deletions(-)

diff --git a/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/Clazz.java b/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/Clazz.java
new file mode 100644
index 0000000..2c1a09e
--- /dev/null
+++ b/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/Clazz.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.tomee.patch.core;
+
+import java.io.File;
+import java.util.Objects;
+
+public class Clazz {
+    private final String name;
+    private final String prefix;
+    private final File file;
+
+    public Clazz(final String name, final File file) {
+        this.name = name;
+        this.prefix = name.replaceAll("\\.class$", "");
+        this.file = file;
+    }
+
+    public String getPrefix() {
+        return prefix;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public File getFile() {
+        return file;
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        final Clazz clazz = (Clazz) o;
+        return name.equals(clazz.name);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(name);
+    }
+}
diff --git a/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/Log.java b/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/Log.java
new file mode 100644
index 0000000..1819d3f
--- /dev/null
+++ b/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/Log.java
@@ -0,0 +1,35 @@
+package org.apache.tomee.patch.core;
+
+public interface Log {
+    boolean isDebugEnabled();
+
+    void debug(CharSequence var1);
+
+    void debug(CharSequence var1, Throwable var2);
+
+    void debug(Throwable var1);
+
+    boolean isInfoEnabled();
+
+    void info(CharSequence var1);
+
+    void info(CharSequence var1, Throwable var2);
+
+    void info(Throwable var1);
+
+    boolean isWarnEnabled();
+
+    void warn(CharSequence var1);
+
+    void warn(CharSequence var1, Throwable var2);
+
+    void warn(Throwable var1);
+
+    boolean isErrorEnabled();
+
+    void error(CharSequence var1);
+
+    void error(CharSequence var1, Throwable var2);
+
+    void error(Throwable var1);
+}
diff --git a/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/NullLog.java b/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/NullLog.java
new file mode 100644
index 0000000..180c346
--- /dev/null
+++ b/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/NullLog.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.tomee.patch.core;
+
+public class NullLog implements Log {
+    @Override
+    public boolean isDebugEnabled() {
+        return false;
+    }
+
+    @Override
+    public void debug(final CharSequence var1) {
+
+    }
+
+    @Override
+    public void debug(final CharSequence var1, final Throwable var2) {
+
+    }
+
+    @Override
+    public void debug(final Throwable var1) {
+
+    }
+
+    @Override
+    public boolean isInfoEnabled() {
+        return false;
+    }
+
+    @Override
+    public void info(final CharSequence var1) {
+
+    }
+
+    @Override
+    public void info(final CharSequence var1, final Throwable var2) {
+
+    }
+
+    @Override
+    public void info(final Throwable var1) {
+
+    }
+
+    @Override
+    public boolean isWarnEnabled() {
+        return false;
+    }
+
+    @Override
+    public void warn(final CharSequence var1) {
+
+    }
+
+    @Override
+    public void warn(final CharSequence var1, final Throwable var2) {
+
+    }
+
+    @Override
+    public void warn(final Throwable var1) {
+
+    }
+
+    @Override
+    public boolean isErrorEnabled() {
+        return false;
+    }
+
+    @Override
+    public void error(final CharSequence var1) {
+
+    }
+
+    @Override
+    public void error(final CharSequence var1, final Throwable var2) {
+
+    }
+
+    @Override
+    public void error(final Throwable var1) {
+
+    }
+}
diff --git a/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/Transformation.java b/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/Transformation.java
index 8f05c8e..53bb1d8 100644
--- a/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/Transformation.java
+++ b/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/Transformation.java
@@ -25,27 +25,52 @@ import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
 import java.util.zip.ZipOutputStream;
 
 public class Transformation {
 
-    private Transformation() {
+    private final List<Clazz> classes = new ArrayList<Clazz>();
+    private final Log log;
+
+    public Transformation() {
+        this.log = new NullLog();
+    }
+
+
+    public Transformation(final List<Clazz> classes, final Log log) {
+        this.classes.addAll(classes);
+        this.log = log;
     }
 
     public static File transform(final File jar) throws IOException {
+        return new Transformation().transformArchive(jar);
+    }
+
+    public File transformArchive(final File jar) throws IOException {
         final File tempFile = File.createTempFile(jar.getName(), ".transformed");
 
         try (final InputStream inputStream = IO.read(jar)) {
             try (final OutputStream outputStream = IO.write(tempFile)) {
-                scanJar(inputStream, outputStream);
+                final Jar old = Jar.enter(jar.getName());
+                try {
+                    scanJar(inputStream, outputStream);
+                } finally {
+                    Jar.exit(old);
+                }
                 return tempFile;
             }
         }
     }
 
-    private static void scanJar(final InputStream inputStream, final OutputStream outputStream) throws IOException {
+    private void scanJar(final InputStream inputStream, final OutputStream outputStream) throws IOException {
         final ZipInputStream zipInputStream = new ZipInputStream(inputStream);
         final ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);
 
@@ -53,9 +78,20 @@ public class Transformation {
         while ((oldEntry = zipInputStream.getNextEntry()) != null) {
             // TODO: the name may be changed in transformation
             final String path = oldEntry.getName();
+
+            /*
+             * If this entry has been patched, skip it
+             * We will add the patched version at the end
+             */
+            if (isPatched(path)) {
+                log.debug("Skipping class " + path);
+                IO.copy(zipInputStream, skipped);
+                continue;
+            }
+
             final ZipEntry newEntry = new ZipEntry(path);
 
-            copyAttributes(oldEntry, newEntry);
+//            copyAttributes(oldEntry, newEntry);
 
             zipOutputStream.putNextEntry(newEntry);
 
@@ -63,7 +99,12 @@ public class Transformation {
                 if (path.endsWith(".class")) {
                     scanClass(zipInputStream, zipOutputStream);
                 } else if (isZip(path)) {
-                    scanJar(zipInputStream, zipOutputStream);
+                    final Jar old = Jar.enter(path);
+                    try {
+                        scanJar(zipInputStream, zipOutputStream);
+                    } finally {
+                        Jar.exit(old); // restore the old state
+                    }
                 } else {
                     IO.copy(zipInputStream, zipOutputStream);
                 }
@@ -71,6 +112,23 @@ public class Transformation {
                 zipOutputStream.closeEntry();
             }
         }
+
+        // If we skipped any classes, add them now
+        if (Jar.current().hasPatches()) {
+            log.info("Patching " + Jar.current().getName());
+            for (final Clazz clazz : Jar.current().getSkipped()) {
+                log.info("Applying patch " + clazz.getName());
+
+                final ZipEntry newEntry = new ZipEntry(clazz.getName());
+                zipOutputStream.putNextEntry(newEntry);
+
+                // Run any transformations on these classes as well
+                scanClass(IO.read(clazz.getFile()), zipOutputStream);
+
+                zipOutputStream.closeEntry();
+            }
+        }
+
         zipOutputStream.close();
     }
 
@@ -98,4 +156,64 @@ public class Transformation {
         outputStream.write(bytes);
     }
 
+    public static class Jar {
+        private static final AtomicReference<Jar> current = new AtomicReference<>(new Jar("<none>"));
+
+        private final Set<Clazz> patches = new HashSet<>();
+        private final String name;
+
+        public Jar(final String name) {
+            this.name = name;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public boolean hasPatches() {
+            return patches.size() > 0;
+        }
+
+        public static Jar current() {
+            return current.get();
+        }
+
+        public static Jar enter(final String name) {
+            return current.getAndSet(new Jar(name));
+        }
+
+        public static void exit(final Jar oldJar) {
+            current.getAndSet(oldJar);
+        }
+
+        public Collection<Clazz> getSkipped() {
+            return patches;
+        }
+
+        /**
+         * Select all classes that are a patch for the specified class.
+         * This will also add any applicable inner-classes of the specified class
+         */
+        public void patch(final Clazz clazz, final List<Clazz> potentialPatches) {
+            potentialPatches.stream()
+                    .filter(potentialPatch -> potentialPatch.getName().startsWith(clazz.getPrefix()))
+                    .forEach(patches::add);
+        }
+    }
+
+    private boolean isPatched(final String path) {
+        for (final Clazz clazz : classes) {
+            if (path.startsWith(clazz.getPrefix())) {
+                Jar.current().patch(clazz, classes);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static final OutputStream skipped = new OutputStream() {
+        @Override
+        public void write(final int b) {
+        }
+    };
 }
diff --git a/tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/MavenLog.java b/tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/MavenLog.java
new file mode 100644
index 0000000..9a088b2
--- /dev/null
+++ b/tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/MavenLog.java
@@ -0,0 +1,76 @@
+package org.apache.tomee.patch.plugin;
+
+
+import org.apache.maven.plugin.logging.Log;
+
+public class MavenLog implements org.apache.tomee.patch.core.Log {
+    private final Log log;
+
+    public MavenLog(final Log log) {
+        this.log = log;
+    }
+
+    public boolean isDebugEnabled() {
+        return log.isDebugEnabled();
+    }
+
+    public void debug(final CharSequence charSequence) {
+        log.debug(charSequence);
+    }
+
+    public void debug(final CharSequence charSequence, final Throwable throwable) {
+        log.debug(charSequence, throwable);
+    }
+
+    public void debug(final Throwable throwable) {
+        log.debug(throwable);
+    }
+
+    public boolean isInfoEnabled() {
+        return log.isInfoEnabled();
+    }
+
+    public void info(final CharSequence charSequence) {
+        log.info(charSequence);
+    }
+
+    public void info(final CharSequence charSequence, final Throwable throwable) {
+        log.info(charSequence, throwable);
+    }
+
+    public void info(final Throwable throwable) {
+        log.info(throwable);
+    }
+
+    public boolean isWarnEnabled() {
+        return log.isWarnEnabled();
+    }
+
+    public void warn(final CharSequence charSequence) {
+        log.warn(charSequence);
+    }
+
+    public void warn(final CharSequence charSequence, final Throwable throwable) {
+        log.warn(charSequence, throwable);
+    }
+
+    public void warn(final Throwable throwable) {
+        log.warn(throwable);
+    }
+
+    public boolean isErrorEnabled() {
+        return log.isErrorEnabled();
+    }
+
+    public void error(final CharSequence charSequence) {
+        log.error(charSequence);
+    }
+
+    public void error(final CharSequence charSequence, final Throwable throwable) {
+        log.error(charSequence, throwable);
+    }
+
+    public void error(final Throwable throwable) {
+        log.error(throwable);
+    }
+}
diff --git a/tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/PatchMojo.java b/tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/PatchMojo.java
index bcf8ab8..e4e4ed8 100644
--- a/tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/PatchMojo.java
+++ b/tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/PatchMojo.java
@@ -17,8 +17,6 @@
 package org.apache.tomee.patch.plugin;
 
 import org.apache.maven.artifact.Artifact;
-import org.apache.maven.artifact.factory.ArtifactFactory;
-import org.apache.maven.artifact.resolver.ArtifactResolver;
 import org.apache.maven.execution.MavenSession;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
@@ -28,10 +26,11 @@ 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.apache.maven.project.MavenProjectHelper;
 import org.apache.maven.toolchain.Toolchain;
 import org.apache.maven.toolchain.ToolchainManager;
+import org.apache.tomee.patch.core.Clazz;
 import org.apache.tomee.patch.core.Is;
+import org.apache.tomee.patch.core.Transformation;
 import org.codehaus.plexus.compiler.Compiler;
 import org.codehaus.plexus.compiler.CompilerConfiguration;
 import org.codehaus.plexus.compiler.CompilerMessage;
@@ -39,7 +38,9 @@ import org.codehaus.plexus.compiler.CompilerResult;
 import org.codehaus.plexus.compiler.manager.CompilerManager;
 import org.codehaus.plexus.compiler.manager.NoSuchCompilerException;
 import org.tomitribe.jkta.usage.Dir;
+import org.tomitribe.jkta.util.Paths;
 import org.tomitribe.util.Files;
+import org.tomitribe.util.IO;
 import org.tomitribe.util.Zips;
 
 import java.io.File;
@@ -159,7 +160,7 @@ public class PatchMojo extends AbstractMojo {
     public void execute() throws MojoExecutionException, CompilationFailureException {
         try {
             Files.mkdir(patchClasspathDirectory);
-            
+
             // Select the zip files and jars we'll be potentially patching
             final List<Artifact> artifacts = getPatchArtifacts();
 
@@ -168,11 +169,28 @@ public class PatchMojo extends AbstractMojo {
 
             compile(patchSourceDirectory, jars);
 
+            final List<Clazz> clazzes = classes();
+
+            final Transformation transformation = new Transformation(clazzes, new MavenLog(getLog()));
+            for (final Artifact artifact : artifacts) {
+                final File file = artifact.getFile();
+                getLog().debug("Patching " + file.getAbsolutePath());
+                final File patched = transformation.transformArchive(file);
+                IO.copy(patched, file);
+            }
+
         } catch (IOException e) {
             throw new MojoExecutionException("Error occurred during execution", e);
         }
     }
 
+    private List<Clazz> classes() {
+        return Dir.from(buildDirectory).files()
+                .filter(file -> file.getName().endsWith(".class"))
+                .map(file -> new Clazz(Paths.childPath(buildDirectory, file), file))
+                .collect(Collectors.toList());
+    }
+
     /**
      * Any zip files contained in the Artifact set should be extracted
      * Any jar files contained in the Artifact set will be returned as-is


[tomee-patch-plugin] 02/04: Build a compile-time classpath from the zips being patched

Posted by db...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dblevins pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tomee-patch-plugin.git

commit c58fe32818e08ebfab14b61354cfb39771d660c2
Author: David Blevins <da...@gmail.com>
AuthorDate: Thu Jun 11 19:26:49 2020 -0700

    Build a compile-time classpath from the zips being patched
---
 .../org/apache/tomee/patch/plugin/PatchMojo.java   | 301 +++++++++++++--------
 1 file changed, 188 insertions(+), 113 deletions(-)

diff --git a/tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/PatchMojo.java b/tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/PatchMojo.java
index a237085..ef995d4 100644
--- a/tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/PatchMojo.java
+++ b/tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/PatchMojo.java
@@ -31,12 +31,14 @@ import org.apache.maven.project.MavenProject;
 import org.apache.maven.project.MavenProjectHelper;
 import org.apache.maven.toolchain.Toolchain;
 import org.apache.maven.toolchain.ToolchainManager;
+import org.apache.tomee.patch.core.Is;
 import org.codehaus.plexus.compiler.Compiler;
 import org.codehaus.plexus.compiler.CompilerConfiguration;
 import org.codehaus.plexus.compiler.CompilerMessage;
 import org.codehaus.plexus.compiler.CompilerResult;
 import org.codehaus.plexus.compiler.manager.CompilerManager;
 import org.codehaus.plexus.compiler.manager.NoSuchCompilerException;
+import org.tomitribe.jkta.usage.Dir;
 import org.tomitribe.util.Files;
 import org.tomitribe.util.Zips;
 
@@ -48,6 +50,8 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Predicate;
+import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
@@ -63,10 +67,16 @@ public class PatchMojo extends AbstractMojo {
     @Parameter(defaultValue = "${project.build.directory}", required = true)
     private File outputDirectory;
 
-    @Parameter(defaultValue = "${project.basedir}/src/main/patch", required = true)
+    @Parameter(defaultValue = "${project.basedir}/src/patch/java", required = true)
     private File patchSourceDirectory;
 
     /**
+     * Regex to identify which archives should be matched
+     */
+    @Parameter(defaultValue = "jakartaee9.*\\.zip", required = true)
+    private String select;
+
+    /**
      * <p>
      * Specify the requirements for this jdk toolchain.
      * This overrules the toolchain selected by the maven-toolchain-plugin.
@@ -99,10 +109,17 @@ public class PatchMojo extends AbstractMojo {
     /**
      * The target directory of the compiler if fork is true.
      */
-    @Parameter(defaultValue = "${project.build.directory}", required = true, readonly = true)
+    @Parameter(defaultValue = "${project.build.directory}/patch-classes", required = true, readonly = true)
     private File buildDirectory;
 
     /**
+     * The directory where we will extract the zips being patched so we can compile the
+     * patch source against the jars contained within.
+     */
+    @Parameter(defaultValue = "${project.build.directory}/patch-classpath", required = true)
+    private File patchClasspathDirectory;
+
+    /**
      * The -encoding argument for the Java compiler.
      *
      * @since 2.1
@@ -153,134 +170,192 @@ public class PatchMojo extends AbstractMojo {
      */
     public void execute() throws MojoExecutionException, CompilationFailureException {
         try {
-            final List<Artifact> artifacts = Stream.of(getSourceArtifacts())
-                    .filter(artifact -> artifact.getFile().getName().contains("jakartaee9"))
-                    .collect(Collectors.toList());
+            Files.mkdir(patchClasspathDirectory);
+            
+            // Select the zip files and jars we'll be potentially patching
+            final List<Artifact> artifacts = getPatchArtifacts();
 
-            final File archives = new File(outputDirectory, "patch");
-            Files.mkdir(archives);
+            // Extract any zips and return a list of jars
+            final List<File> jars = prepareJars(artifacts);
 
-            Compiler compiler;
+            compile(patchSourceDirectory, jars);
 
-            getLog().debug("Using compiler '" + compilerId + "'.");
+        } catch (IOException e) {
+            throw new MojoExecutionException("Error occurred during execution", e);
+        }
+    }
 
-            try {
-                compiler = compilerManager.getCompiler(compilerId);
-            } catch (NoSuchCompilerException e) {
-                throw new MojoExecutionException("No such compiler '" + e.getCompilerId() + "'.");
-            }
+    /**
+     * Any zip files contained in the Artifact set should be extracted
+     * Any jar files contained in the Artifact set will be returned as-is
+     */
+    private List<File> prepareJars(final List<Artifact> artifacts) throws IOException {
 
-            Toolchain tc = getToolchain();
-            if (tc != null) {
-                getLog().info("Toolchain in maven-compiler-plugin: " + tc);
-                //TODO somehow shaky dependency between compilerId and tool executable.
-                executable = tc.findTool(compilerId);
+        // Extract all zip, war, ear, rar files.  Do not extract jar files.
+        for (final Artifact artifact : artifacts) {
+            if (isZip(artifact.getFile()) && !isJar(artifact.getFile())) {
+                Zips.unzip(artifact.getFile(), patchClasspathDirectory);
             }
+        }
 
-            final CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
-            compilerConfiguration.setOutputLocation(outputDirectory.getAbsolutePath());
-            compilerConfiguration.setOptimize(false);
-            compilerConfiguration.setDebug(true);
-            compilerConfiguration.setParameters(false);
-            compilerConfiguration.setVerbose(false);
-            compilerConfiguration.setShowWarnings(false);
-            compilerConfiguration.setFailOnWarning(false);
-            compilerConfiguration.setShowDeprecation(false);
-            compilerConfiguration.setSourceVersion(source);
-            compilerConfiguration.setTargetVersion(target);
-            compilerConfiguration.setReleaseVersion(null);
-            compilerConfiguration.setProc(null);
-            compilerConfiguration.setSourceLocations(getPatchSourceLocations());
-            compilerConfiguration.setAnnotationProcessors(null);
-            compilerConfiguration.setSourceEncoding(encoding);
-            compilerConfiguration.setFork(true);
-            compilerConfiguration.setExecutable(executable);
-            compilerConfiguration.setWorkingDirectory(basedir);
-            compilerConfiguration.setCompilerVersion(compilerVersion);
-            compilerConfiguration.setBuildDirectory(buildDirectory);
-            compilerConfiguration.setOutputFileName(null);
-
-            final CompilerResult compilerResult;
-            try {
-                compilerResult = compiler.performCompile(compilerConfiguration);
-            } catch (Exception e) {
-                throw new MojoExecutionException("Fatal error compiling", e);
-            }
+        // Collect a list of jars
+        final List<File> jars = new ArrayList<>();
 
-            List<CompilerMessage> warnings = new ArrayList<>();
-            List<CompilerMessage> errors = new ArrayList<>();
-            List<CompilerMessage> others = new ArrayList<>();
-            for (CompilerMessage message : compilerResult.getCompilerMessages()) {
-                if (message.getKind() == CompilerMessage.Kind.ERROR) {
-                    errors.add(message);
-                } else if (message.getKind() == CompilerMessage.Kind.WARNING
-                        || message.getKind() == CompilerMessage.Kind.MANDATORY_WARNING) {
-                    warnings.add(message);
-                } else {
-                    others.add(message);
-                }
+        // Add any artifacts that are already jars
+        artifacts.stream()
+                .map(Artifact::getFile)
+                .filter(File::isFile)
+                .filter(this::isJar)
+                .forEach(jars::add);
+
+        // Add any extracted files that are jars
+        Dir.from(patchClasspathDirectory)
+                .files()
+                .filter(File::isFile)
+                .filter(this::isJar)
+                .forEach(jars::add);
+
+        return jars;
+    }
+
+    private boolean isJar(final File file) {
+        return file.getName().endsWith(".jar");
+    }
+
+    private static boolean isZip(final File file) {
+        return new Is.Zip().accept(file);
+    }
+
+    private List<Artifact> getPatchArtifacts() {
+        final Predicate<String> match = Pattern.compile(select).asPredicate();
+        return Stream.of(getSourceArtifacts())
+                .filter(artifact -> match.test(artifact.getFile().getName()))
+                .collect(Collectors.toList());
+    }
+
+    private void compile(final File patchSourceDirectory, final List<File> jars) throws MojoExecutionException, CompilationFailureException {
+
+        getLog().debug("Using compiler '" + compilerId + "'.");
+
+        final Compiler compiler;
+
+        try {
+            compiler = compilerManager.getCompiler(compilerId);
+        } catch (NoSuchCompilerException e) {
+            throw new MojoExecutionException("No such compiler '" + e.getCompilerId() + "'.");
+        }
+
+        final Toolchain tc = getToolchain();
+        if (tc != null) {
+            getLog().info("Toolchain in maven-compiler-plugin: " + tc);
+            //TODO somehow shaky dependency between compilerId and tool executable.
+            executable = tc.findTool(compilerId);
+        }
+
+
+        final CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
+        compilerConfiguration.setOutputLocation(buildDirectory.getAbsolutePath());
+        compilerConfiguration.setOptimize(false);
+        compilerConfiguration.setDebug(true);
+        compilerConfiguration.setParameters(false);
+        compilerConfiguration.setVerbose(false);
+        compilerConfiguration.setShowWarnings(false);
+        compilerConfiguration.setFailOnWarning(false);
+        compilerConfiguration.setShowDeprecation(false);
+        compilerConfiguration.setSourceVersion(source);
+        compilerConfiguration.setTargetVersion(target);
+        compilerConfiguration.setReleaseVersion(null);
+        compilerConfiguration.setProc(null);
+        compilerConfiguration.setSourceLocations(getPatchSourceLocations());
+        compilerConfiguration.setAnnotationProcessors(null);
+        compilerConfiguration.setSourceEncoding(encoding);
+        compilerConfiguration.setFork(true);
+        compilerConfiguration.setExecutable(executable);
+        compilerConfiguration.setWorkingDirectory(basedir);
+        compilerConfiguration.setCompilerVersion(compilerVersion);
+        compilerConfiguration.setBuildDirectory(buildDirectory);
+        compilerConfiguration.setOutputFileName(null);
+
+        // Add each jar as a classpath entry
+        jars.stream()
+                .map(File::getAbsolutePath)
+                .forEach(compilerConfiguration::addClasspathEntry);
+
+        // Now we can compile!
+        final CompilerResult compilerResult;
+        try {
+            compilerResult = compiler.performCompile(compilerConfiguration);
+        } catch (Exception e) {
+            throw new MojoExecutionException("Fatal error compiling", e);
+        }
+
+        List<CompilerMessage> warnings = new ArrayList<>();
+        List<CompilerMessage> errors = new ArrayList<>();
+        List<CompilerMessage> others = new ArrayList<>();
+        for (CompilerMessage message : compilerResult.getCompilerMessages()) {
+            if (message.getKind() == CompilerMessage.Kind.ERROR) {
+                errors.add(message);
+            } else if (message.getKind() == CompilerMessage.Kind.WARNING
+                    || message.getKind() == CompilerMessage.Kind.MANDATORY_WARNING) {
+                warnings.add(message);
+            } else {
+                others.add(message);
             }
+        }
 
-            if (true && !compilerResult.isSuccess()) {
-                for (CompilerMessage message : others) {
-                    assert message.getKind() != CompilerMessage.Kind.ERROR
-                            && message.getKind() != CompilerMessage.Kind.WARNING
-                            && message.getKind() != CompilerMessage.Kind.MANDATORY_WARNING;
-                    getLog().info(message.toString());
-                }
-                if (!warnings.isEmpty()) {
-                    getLog().info("-------------------------------------------------------------");
-                    getLog().warn("COMPILATION WARNING : ");
-                    getLog().info("-------------------------------------------------------------");
-                    for (CompilerMessage warning : warnings) {
-                        getLog().warn(warning.toString());
-                    }
-                    getLog().info(warnings.size() + ((warnings.size() > 1) ? " warnings " : " warning"));
-                    getLog().info("-------------------------------------------------------------");
+        if (!compilerResult.isSuccess()) {
+            for (CompilerMessage message : others) {
+                assert message.getKind() != CompilerMessage.Kind.ERROR
+                        && message.getKind() != CompilerMessage.Kind.WARNING
+                        && message.getKind() != CompilerMessage.Kind.MANDATORY_WARNING;
+                getLog().info(message.toString());
+            }
+            if (!warnings.isEmpty()) {
+                getLog().info("-------------------------------------------------------------");
+                getLog().warn("COMPILATION WARNING : ");
+                getLog().info("-------------------------------------------------------------");
+                for (CompilerMessage warning : warnings) {
+                    getLog().warn(warning.toString());
                 }
+                getLog().info(warnings.size() + ((warnings.size() > 1) ? " warnings " : " warning"));
+                getLog().info("-------------------------------------------------------------");
+            }
 
-                if (!errors.isEmpty()) {
-                    getLog().info("-------------------------------------------------------------");
-                    getLog().error("COMPILATION ERROR : ");
-                    getLog().info("-------------------------------------------------------------");
-                    for (CompilerMessage error : errors) {
-                        getLog().error(error.toString());
-                    }
-                    getLog().info(errors.size() + ((errors.size() > 1) ? " errors " : " error"));
-                    getLog().info("-------------------------------------------------------------");
+            if (!errors.isEmpty()) {
+                getLog().info("-------------------------------------------------------------");
+                getLog().error("COMPILATION ERROR : ");
+                getLog().info("-------------------------------------------------------------");
+                for (CompilerMessage error : errors) {
+                    getLog().error(error.toString());
                 }
+                getLog().info(errors.size() + ((errors.size() > 1) ? " errors " : " error"));
+                getLog().info("-------------------------------------------------------------");
+            }
 
-                if (!errors.isEmpty()) {
-                    throw new CompilationFailureException(errors);
-                } else {
-                    throw new CompilationFailureException(warnings);
-                }
+            if (!errors.isEmpty()) {
+                throw new CompilationFailureException(errors);
             } else {
-                for (CompilerMessage message : compilerResult.getCompilerMessages()) {
-                    switch (message.getKind()) {
-                        case NOTE:
-                        case OTHER:
-                            getLog().info(message.toString());
-                            break;
-
-                        case ERROR:
-                            getLog().error(message.toString());
-                            break;
-
-                        case MANDATORY_WARNING:
-                        case WARNING:
-                        default:
-                            getLog().warn(message.toString());
-                            break;
-                    }
-                }
+                throw new CompilationFailureException(warnings);
             }
-
-            for (final Artifact artifact : artifacts) {
-                Zips.unzip(artifact.getFile(), archives);
+        } else {
+            for (CompilerMessage message : compilerResult.getCompilerMessages()) {
+                switch (message.getKind()) {
+                    case NOTE:
+                    case OTHER:
+                        getLog().info(message.toString());
+                        break;
+
+                    case ERROR:
+                        getLog().error(message.toString());
+                        break;
+
+                    case MANDATORY_WARNING:
+                    case WARNING:
+                    default:
+                        getLog().warn(message.toString());
+                        break;
+                }
             }
-        } catch (IOException e) {
-            throw new MojoExecutionException("Error occurred during execution", e);
         }
     }
 


[tomee-patch-plugin] 01/04: Rough compilation capabilities lifted from maven-compile-plugin

Posted by db...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dblevins pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tomee-patch-plugin.git

commit ebe5dad8698a1e0f1a2679f2fb7651e7563389d6
Author: David Blevins <da...@gmail.com>
AuthorDate: Thu Jun 11 15:51:21 2020 -0700

    Rough compilation capabilities lifted from maven-compile-plugin
---
 tomee-patch-plugin/pom.xml                         |  49 ++-
 .../patch/plugin/CompilationFailureException.java  |  85 +++++
 .../org/apache/tomee/patch/plugin/PatchMojo.java   | 349 +++++++++++++++++++++
 .../apache/tomee/patch/plugin/TransformMojo.java   |  33 --
 4 files changed, 482 insertions(+), 34 deletions(-)

diff --git a/tomee-patch-plugin/pom.xml b/tomee-patch-plugin/pom.xml
index f68116a..2d7ff90 100644
--- a/tomee-patch-plugin/pom.xml
+++ b/tomee-patch-plugin/pom.xml
@@ -33,11 +33,18 @@
 
   <properties>
     <maven.version>3.2.2</maven.version>
-    <maven-plugin.prefix>transform</maven-plugin.prefix>
+    <maven-plugin.prefix>patch</maven-plugin.prefix>
+    <plexus-compiler.version>2.8.6</plexus-compiler.version>
+    <plexus-java.version>1.0.4</plexus-java.version>
   </properties>
 
   <dependencies>
     <dependency>
+      <groupId>org.apache.tomee.patch</groupId>
+      <artifactId>tomee-patch-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
       <groupId>org.apache.maven.plugin-tools</groupId>
       <artifactId>maven-plugin-annotations</artifactId>
       <version>3.3</version>
@@ -48,6 +55,46 @@
       <version>3.0.17</version>
     </dependency>
     <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-java</artifactId>
+      <version>${plexus-java.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-compiler-api</artifactId>
+      <version>${plexus-compiler.version}</version>
+      <exclusions>
+        <exclusion>
+          <groupId>org.codehaus.plexus</groupId>
+          <artifactId>plexus-component-api</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-compiler-manager</artifactId>
+      <version>${plexus-compiler.version}</version>
+      <exclusions>
+        <exclusion>
+          <groupId>org.codehaus.plexus</groupId>
+          <artifactId>plexus-component-api</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-compiler-javac</artifactId>
+      <version>${plexus-compiler.version}</version>
+      <scope>runtime</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>org.codehaus.plexus</groupId>
+          <artifactId>plexus-component-api</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
       <groupId>org.apache.maven</groupId>
       <artifactId>maven-plugin-api</artifactId>
       <version>${maven.version}</version>
diff --git a/tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/CompilationFailureException.java b/tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/CompilationFailureException.java
new file mode 100644
index 0000000..93c1592
--- /dev/null
+++ b/tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/CompilationFailureException.java
@@ -0,0 +1,85 @@
+package org.apache.tomee.patch.plugin;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.maven.plugin.MojoFailureException;
+import org.codehaus.plexus.compiler.CompilerMessage;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
+ * @since 2.0
+ */
+@SuppressWarnings( "serial" )
+public class CompilationFailureException
+    extends MojoFailureException
+{
+    private static final String LS = System.getProperty( "line.separator" );
+
+    /**
+     * Wrap error messages from the compiler
+     *
+     * @param messages the messages, not null
+     * @since 2.0
+     */
+    public CompilationFailureException(List<CompilerMessage> messages )
+    {
+        super( null, shortMessage( messages ), longMessage( messages ) );
+    }
+
+    /**
+     * Long message will have all messages, one per line
+     *
+     * @param messages the messages, not null
+     * @return the long error message
+     * @since 2.0
+     */
+    public static String longMessage( List<CompilerMessage> messages )
+    {
+        StringBuilder sb = new StringBuilder();
+
+        for ( CompilerMessage compilerError : messages )
+        {
+            sb.append( compilerError ).append( LS );
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * Short message will have the error message if there's only one, useful for errors forking the compiler
+     *
+     * @param messages the messages, not null
+     * @return the short error message
+     * @since 2.0.2
+     */
+    public static String shortMessage( List<CompilerMessage> messages )
+    {
+        StringBuilder sb = new StringBuilder( "Compilation failure" );
+
+        if ( messages.size() == 1 )
+        {
+            sb.append( LS ).append( messages.get( 0 ) ).append( LS );
+        }
+
+        return sb.toString();
+    }
+}
diff --git a/tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/PatchMojo.java b/tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/PatchMojo.java
new file mode 100644
index 0000000..a237085
--- /dev/null
+++ b/tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/PatchMojo.java
@@ -0,0 +1,349 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.tomee.patch.plugin;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.factory.ArtifactFactory;
+import org.apache.maven.artifact.resolver.ArtifactResolver;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+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;
+import org.apache.maven.plugins.annotations.ResolutionScope;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.project.MavenProjectHelper;
+import org.apache.maven.toolchain.Toolchain;
+import org.apache.maven.toolchain.ToolchainManager;
+import org.codehaus.plexus.compiler.Compiler;
+import org.codehaus.plexus.compiler.CompilerConfiguration;
+import org.codehaus.plexus.compiler.CompilerMessage;
+import org.codehaus.plexus.compiler.CompilerResult;
+import org.codehaus.plexus.compiler.manager.CompilerManager;
+import org.codehaus.plexus.compiler.manager.NoSuchCompilerException;
+import org.tomitribe.util.Files;
+import org.tomitribe.util.Zips;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+@Mojo(name = "run", requiresDependencyResolution = ResolutionScope.RUNTIME_PLUS_SYSTEM, defaultPhase = LifecyclePhase.PACKAGE, requiresProject = true, threadSafe = true)
+public class PatchMojo extends AbstractMojo {
+
+    @Parameter(defaultValue = "${project}", readonly = true, required = true)
+    private MavenProject project;
+
+    @Parameter(defaultValue = "${session}", readonly = true, required = true)
+    private MavenSession session;
+
+    @Parameter(defaultValue = "${project.build.directory}", required = true)
+    private File outputDirectory;
+
+    @Parameter(defaultValue = "${project.basedir}/src/main/patch", required = true)
+    private File patchSourceDirectory;
+
+    /**
+     * <p>
+     * Specify the requirements for this jdk toolchain.
+     * This overrules the toolchain selected by the maven-toolchain-plugin.
+     * </p>
+     * <strong>note:</strong> requires at least Maven 3.3.1
+     *
+     * @since 3.6
+     */
+    @Parameter
+    private Map<String, String> jdkToolchain;
+
+    /**
+     * Sets the executable of the compiler to use when {@link #fork} is <code>true</code>.
+     */
+    @Parameter(property = "maven.compiler.executable")
+    private String executable;
+
+    /**
+     * Version of the compiler to use, ex. "1.3", "1.5", if {@link #fork} is set to <code>true</code>.
+     */
+    @Parameter(property = "maven.compiler.compilerVersion")
+    private String compilerVersion;
+
+    /**
+     * The directory to run the compiler from if fork is true.
+     */
+    @Parameter(defaultValue = "${basedir}", required = true, readonly = true)
+    private File basedir;
+
+    /**
+     * The target directory of the compiler if fork is true.
+     */
+    @Parameter(defaultValue = "${project.build.directory}", required = true, readonly = true)
+    private File buildDirectory;
+
+    /**
+     * The -encoding argument for the Java compiler.
+     *
+     * @since 2.1
+     */
+    @Parameter(property = "encoding", defaultValue = "${project.build.sourceEncoding}")
+    private String encoding;
+
+    @Component
+    private MavenProjectHelper projectHelper;
+
+    @Component
+    protected ArtifactFactory factory;
+
+    @Component
+    protected ArtifactResolver resolver;
+
+    /**
+     * Plexus compiler manager.
+     */
+    @Component
+    private CompilerManager compilerManager;
+
+    @Component
+    private ToolchainManager toolchainManager;
+
+    /**
+     * <p>The -source argument for the Java compiler.</p>
+     */
+    @Parameter(property = "maven.compiler.source", defaultValue = "1.8")
+    protected String source;
+
+    /**
+     * <p>The -target argument for the Java compiler.</p>
+     */
+    @Parameter(property = "maven.compiler.target", defaultValue = "1.8")
+    protected String target;
+
+    /**
+     * The compiler id of the compiler to use. See this
+     * <a href="non-javac-compilers.html">guide</a> for more information.
+     */
+    @Parameter(property = "maven.compiler.compilerId", defaultValue = "javac")
+    private String compilerId;
+
+    /**
+     * Main execution point of the plugin. This looks at the attached artifacts, and runs the transformer on them.
+     * @throws MojoExecutionException Thrown if there is an error during plugin execution
+     */
+    public void execute() throws MojoExecutionException, CompilationFailureException {
+        try {
+            final List<Artifact> artifacts = Stream.of(getSourceArtifacts())
+                    .filter(artifact -> artifact.getFile().getName().contains("jakartaee9"))
+                    .collect(Collectors.toList());
+
+            final File archives = new File(outputDirectory, "patch");
+            Files.mkdir(archives);
+
+            Compiler compiler;
+
+            getLog().debug("Using compiler '" + compilerId + "'.");
+
+            try {
+                compiler = compilerManager.getCompiler(compilerId);
+            } catch (NoSuchCompilerException e) {
+                throw new MojoExecutionException("No such compiler '" + e.getCompilerId() + "'.");
+            }
+
+            Toolchain tc = getToolchain();
+            if (tc != null) {
+                getLog().info("Toolchain in maven-compiler-plugin: " + tc);
+                //TODO somehow shaky dependency between compilerId and tool executable.
+                executable = tc.findTool(compilerId);
+            }
+
+            final CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
+            compilerConfiguration.setOutputLocation(outputDirectory.getAbsolutePath());
+            compilerConfiguration.setOptimize(false);
+            compilerConfiguration.setDebug(true);
+            compilerConfiguration.setParameters(false);
+            compilerConfiguration.setVerbose(false);
+            compilerConfiguration.setShowWarnings(false);
+            compilerConfiguration.setFailOnWarning(false);
+            compilerConfiguration.setShowDeprecation(false);
+            compilerConfiguration.setSourceVersion(source);
+            compilerConfiguration.setTargetVersion(target);
+            compilerConfiguration.setReleaseVersion(null);
+            compilerConfiguration.setProc(null);
+            compilerConfiguration.setSourceLocations(getPatchSourceLocations());
+            compilerConfiguration.setAnnotationProcessors(null);
+            compilerConfiguration.setSourceEncoding(encoding);
+            compilerConfiguration.setFork(true);
+            compilerConfiguration.setExecutable(executable);
+            compilerConfiguration.setWorkingDirectory(basedir);
+            compilerConfiguration.setCompilerVersion(compilerVersion);
+            compilerConfiguration.setBuildDirectory(buildDirectory);
+            compilerConfiguration.setOutputFileName(null);
+
+            final CompilerResult compilerResult;
+            try {
+                compilerResult = compiler.performCompile(compilerConfiguration);
+            } catch (Exception e) {
+                throw new MojoExecutionException("Fatal error compiling", e);
+            }
+
+            List<CompilerMessage> warnings = new ArrayList<>();
+            List<CompilerMessage> errors = new ArrayList<>();
+            List<CompilerMessage> others = new ArrayList<>();
+            for (CompilerMessage message : compilerResult.getCompilerMessages()) {
+                if (message.getKind() == CompilerMessage.Kind.ERROR) {
+                    errors.add(message);
+                } else if (message.getKind() == CompilerMessage.Kind.WARNING
+                        || message.getKind() == CompilerMessage.Kind.MANDATORY_WARNING) {
+                    warnings.add(message);
+                } else {
+                    others.add(message);
+                }
+            }
+
+            if (true && !compilerResult.isSuccess()) {
+                for (CompilerMessage message : others) {
+                    assert message.getKind() != CompilerMessage.Kind.ERROR
+                            && message.getKind() != CompilerMessage.Kind.WARNING
+                            && message.getKind() != CompilerMessage.Kind.MANDATORY_WARNING;
+                    getLog().info(message.toString());
+                }
+                if (!warnings.isEmpty()) {
+                    getLog().info("-------------------------------------------------------------");
+                    getLog().warn("COMPILATION WARNING : ");
+                    getLog().info("-------------------------------------------------------------");
+                    for (CompilerMessage warning : warnings) {
+                        getLog().warn(warning.toString());
+                    }
+                    getLog().info(warnings.size() + ((warnings.size() > 1) ? " warnings " : " warning"));
+                    getLog().info("-------------------------------------------------------------");
+                }
+
+                if (!errors.isEmpty()) {
+                    getLog().info("-------------------------------------------------------------");
+                    getLog().error("COMPILATION ERROR : ");
+                    getLog().info("-------------------------------------------------------------");
+                    for (CompilerMessage error : errors) {
+                        getLog().error(error.toString());
+                    }
+                    getLog().info(errors.size() + ((errors.size() > 1) ? " errors " : " error"));
+                    getLog().info("-------------------------------------------------------------");
+                }
+
+                if (!errors.isEmpty()) {
+                    throw new CompilationFailureException(errors);
+                } else {
+                    throw new CompilationFailureException(warnings);
+                }
+            } else {
+                for (CompilerMessage message : compilerResult.getCompilerMessages()) {
+                    switch (message.getKind()) {
+                        case NOTE:
+                        case OTHER:
+                            getLog().info(message.toString());
+                            break;
+
+                        case ERROR:
+                            getLog().error(message.toString());
+                            break;
+
+                        case MANDATORY_WARNING:
+                        case WARNING:
+                        default:
+                            getLog().warn(message.toString());
+                            break;
+                    }
+                }
+            }
+
+            for (final Artifact artifact : artifacts) {
+                Zips.unzip(artifact.getFile(), archives);
+            }
+        } catch (IOException e) {
+            throw new MojoExecutionException("Error occurred during execution", e);
+        }
+    }
+
+    private List<String> getPatchSourceLocations() {
+        return Collections.singletonList(patchSourceDirectory.getAbsolutePath());
+    }
+
+    private void patch(final Artifact artifact) throws IOException {
+        final File file = artifact.getFile();
+
+    }
+
+    //TODO remove the part with ToolchainManager lookup once we depend on
+    //3.0.9 (have it as prerequisite). Define as regular component field then.
+    protected final Toolchain getToolchain() {
+        Toolchain tc = null;
+
+        if (jdkToolchain != null) {
+            // Maven 3.3.1 has plugin execution scoped Toolchain Support
+            try {
+                Method getToolchainsMethod =
+                        toolchainManager.getClass().getMethod("getToolchains", MavenSession.class, String.class,
+                                Map.class);
+
+                @SuppressWarnings("unchecked")
+                List<Toolchain> tcs =
+                        (List<Toolchain>) getToolchainsMethod.invoke(toolchainManager, session, "jdk",
+                                jdkToolchain);
+
+                if (tcs != null && !tcs.isEmpty()) {
+                    tc = tcs.get(0);
+                }
+            } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException
+                    | InvocationTargetException e) {
+                // ignore
+            }
+        }
+
+        if (tc == null) {
+            tc = toolchainManager.getToolchainFromBuildContext("jdk", session);
+        }
+
+        return tc;
+    }
+
+
+    /**
+     * Gets the source artifacts that should be transformed
+     * @return an array to artifacts to be transformed
+     */
+    public Artifact[] getSourceArtifacts() {
+        List<Artifact> artifactList = new ArrayList<Artifact>();
+        if (project.getArtifact() != null && project.getArtifact().getFile() != null) {
+            artifactList.add(project.getArtifact());
+        }
+
+        for (final Artifact attachedArtifact : project.getAttachedArtifacts()) {
+            if (attachedArtifact.getFile() != null) {
+                artifactList.add(attachedArtifact);
+            }
+        }
+
+        return artifactList.toArray(new Artifact[0]);
+    }
+
+}
diff --git a/tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/TransformMojo.java b/tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/TransformMojo.java
deleted file mode 100644
index 27c06ad..0000000
--- a/tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/TransformMojo.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.tomee.patch.plugin;
-
-import org.apache.maven.plugin.AbstractMojo;
-import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugin.MojoFailureException;
-import org.apache.maven.plugins.annotations.LifecyclePhase;
-import org.apache.maven.plugins.annotations.Mojo;
-import org.apache.maven.plugins.annotations.ResolutionScope;
-
-@Mojo(name = "run", requiresDependencyResolution = ResolutionScope.RUNTIME_PLUS_SYSTEM, defaultPhase = LifecyclePhase.PACKAGE, requiresProject = true, threadSafe = true)
-public class TransformMojo extends AbstractMojo {
-
-    @Override
-    public void execute() throws MojoExecutionException, MojoFailureException {
-
-    }
-}