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/11 02:43:57 UTC
[tomee-patch-plugin] 02/02: Initial code forked from
https://github.com/tomitribe/jkta
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 2a06d9f081c1db05164286db9149ba17c30754dc
Author: David Blevins <da...@gmail.com>
AuthorDate: Wed Jun 10 19:33:59 2020 -0700
Initial code forked from https://github.com/tomitribe/jkta
This is a temporary codebase with the goal of getting a completely
running TomEE 8 under the jakarta namespace as soon as possible and
without any overhead of abstractions or dealing with third-party
libraries or third-party communities.
This is intended as a stop-gap and this code base will not live
long-term. Any improvements will be migrated to either the Eclipse
Transformer or Jkta, hopefully making this codebase not necessary.
---
pom.xml | 15 +-
tomee-patch-core/pom.xml | 55 ++-
.../tomee/patch/core/AnnotationTransformer.java | 37 ++
.../apache/tomee/patch/core/ClassTransformer.java | 60 +++
.../java/org/apache/tomee/patch/core/Copy.java | 41 ++
.../apache/tomee/patch/core/FieldTransformer.java | 38 ++
.../main/java/org/apache/tomee/patch/core/Is.java | 39 ++
.../apache/tomee/patch/core/MethodTransformer.java | 118 ++++++
.../apache/tomee/patch/core/ModuleTransformer.java | 26 ++
.../tomee/patch/core/SignatureTransformer.java | 25 ++
.../apache/tomee/patch/core/Transformation.java | 101 +++++
.../src/test/java/javax/ejb/Process.java | 27 ++
.../java/javax/enterprise/context/MockScoped.java | 41 ++
.../src/test/java/javax/jms/Consumer.java | 26 ++
.../java/javax/jms/EnterpriseBeanConsumer.java | 28 ++
.../test/java/javax/persistence/EntityBean.java | 27 ++
.../src/test/java/javax/persistence/Persist.java | 31 ++
.../patch/core/AnnotationTransformerTest.java | 140 +++++++
.../org/apache/tomee/patch/core/ArrayData.java | 48 +++
.../java/org/apache/tomee/patch/core/Asmifier.java | 168 ++++++++
.../java/org/apache/tomee/patch/core/Bytecode.java | 62 +++
.../tomee/patch/core/ClassTransformerTest.java | 285 +++++++++++++
.../java/org/apache/tomee/patch/core/Data.java | 35 ++
.../tomee/patch/core/FieldTransformerTest.java | 95 +++++
.../tomee/patch/core/MethodTransformerTest.java | 445 +++++++++++++++++++++
.../tomee/patch/core/ModuleTransformerTest.java | 21 +
.../java/org/apache/tomee/patch/core/Scan.java | 70 ++++
.../tomee/patch/core/SignatureTransformerTest.java | 38 ++
.../org/apache/tomee/patch/core/Transform.java | 78 ++++
tomee-patch-plugin/pom.xml | 88 ++++
.../apache/tomee/patch/plugin/TransformMojo.java | 33 ++
31 files changed, 2339 insertions(+), 2 deletions(-)
diff --git a/pom.xml b/pom.xml
index de443de..d9ceb64 100644
--- a/pom.xml
+++ b/pom.xml
@@ -29,7 +29,6 @@
<relativePath><!--Resolve on repository--></relativePath>
</parent>
-
<groupId>org.apache.tomee.patch</groupId>
<artifactId>tomee-patch-parent</artifactId>
<packaging>pom</packaging>
@@ -84,5 +83,19 @@
<module>tomee-patch-core</module>
<module>tomee-patch-plugin</module>
</modules>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.8.1</version>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
</project>
diff --git a/tomee-patch-core/pom.xml b/tomee-patch-core/pom.xml
index 93e381c..9ab050c 100644
--- a/tomee-patch-core/pom.xml
+++ b/tomee-patch-core/pom.xml
@@ -29,6 +29,59 @@
</parent>
<artifactId>tomee-patch-core</artifactId>
-
+
+ <dependencies>
+ <dependency>
+ <groupId>org.ow2.asm</groupId>
+ <artifactId>asm</artifactId>
+ <version>8.0.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.ow2.asm</groupId>
+ <artifactId>asm-tree</artifactId>
+ <version>8.0.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.ow2.asm</groupId>
+ <artifactId>asm-analysis</artifactId>
+ <version>8.0.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.ow2.asm</groupId>
+ <artifactId>asm-commons</artifactId>
+ <version>8.0.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.ow2.asm</groupId>
+ <artifactId>asm-util</artifactId>
+ <version>8.0.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.tomitribe</groupId>
+ <artifactId>tomitribe-crest</artifactId>
+ <version>0.14</version>
+ </dependency>
+ <dependency>
+ <groupId>org.tomitribe</groupId>
+ <artifactId>tomitribe-crest-xbean</artifactId>
+ <version>0.14</version>
+ </dependency>
+ <dependency>
+ <groupId>org.tomitribe</groupId>
+ <artifactId>tomitribe-util</artifactId>
+ <version>1.3.13</version>
+ </dependency>
+ <dependency>
+ <groupId>org.tomitribe.jkta</groupId>
+ <artifactId>jkta</artifactId>
+ <version>0.10</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.10</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
</project>
diff --git a/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/AnnotationTransformer.java b/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/AnnotationTransformer.java
new file mode 100644
index 0000000..5269b93
--- /dev/null
+++ b/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/AnnotationTransformer.java
@@ -0,0 +1,37 @@
+/*
+ * 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 org.objectweb.asm.AnnotationVisitor;
+
+public class AnnotationTransformer extends AnnotationVisitor {
+
+ public AnnotationTransformer(final int api, final AnnotationVisitor annotationVisitor) {
+ super(api, annotationVisitor);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String name, final String descriptor) {
+ return new AnnotationTransformer(this.api, super.visitAnnotation(name, descriptor));
+ }
+
+ @Override
+ public AnnotationVisitor visitArray(final String name) {
+ return new AnnotationTransformer(this.api, super.visitArray(name));
+ }
+
+}
diff --git a/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/ClassTransformer.java b/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/ClassTransformer.java
new file mode 100644
index 0000000..64de18a
--- /dev/null
+++ b/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/ClassTransformer.java
@@ -0,0 +1,60 @@
+/*
+ * 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 org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.ModuleVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.TypePath;
+
+public class ClassTransformer extends ClassVisitor {
+
+ private String className;
+
+ public ClassTransformer(final ClassWriter classVisitor) {
+ super(Opcodes.ASM8, classVisitor);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ return new AnnotationTransformer(this.api, super.visitAnnotation(descriptor, visible));
+ }
+
+ @Override
+ public FieldVisitor visitField(final int access, final String name, final String descriptor, final String signature, final Object value) {
+ return new FieldTransformer(this.api, super.visitField(access, name, descriptor, signature, value));
+ }
+
+ @Override
+ public MethodVisitor visitMethod(final int access, final String name, final String descriptor, final String signature, final String[] exceptions) {
+ return new MethodTransformer(this.api, super.visitMethod(access, name, descriptor, signature, exceptions));
+ }
+
+ @Override
+ public ModuleVisitor visitModule(final String name, final int access, final String version) {
+ return new ModuleTransformer(this.api, super.visitModule(name, access, version));
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ return new AnnotationTransformer(this.api, super.visitTypeAnnotation(typeRef, typePath, descriptor, visible));
+ }
+}
diff --git a/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/Copy.java b/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/Copy.java
new file mode 100644
index 0000000..8b7a6cf
--- /dev/null
+++ b/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/Copy.java
@@ -0,0 +1,41 @@
+/*
+ * 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.util.function.BiConsumer;
+import java.util.function.Function;
+
+public class Copy<T> {
+ private final T from;
+ private final T to;
+
+ public Copy(final T from, final T to) {
+ this.from = from;
+ this.to = to;
+
+ }
+
+ public <Value> Copy<T> att(final Function<T, Value> getter, final BiConsumer<T, Value> setter) {
+ final Value value = getter.apply(from);
+ if (value != null) setter.accept(to, value);
+ return this;
+ }
+
+ public static <T> Copy<T> copy(final T from, T to) {
+ return new Copy<>(from, to);
+ }
+}
diff --git a/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/FieldTransformer.java b/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/FieldTransformer.java
new file mode 100644
index 0000000..af92959
--- /dev/null
+++ b/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/FieldTransformer.java
@@ -0,0 +1,38 @@
+/*
+ * 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 org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.TypePath;
+
+public class FieldTransformer extends FieldVisitor {
+
+ public FieldTransformer(final int api, final FieldVisitor fieldVisitor) {
+ super(api, fieldVisitor);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ return new AnnotationTransformer(this.api, super.visitAnnotation(descriptor, visible));
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ return new AnnotationTransformer(this.api, super.visitTypeAnnotation(typeRef, typePath, descriptor, visible));
+ }
+}
diff --git a/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/Is.java b/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/Is.java
new file mode 100644
index 0000000..146c8ce
--- /dev/null
+++ b/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/Is.java
@@ -0,0 +1,39 @@
+/*
+ * 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.io.FileFilter;
+
+public interface Is {
+
+ class Zip implements FileFilter {
+ @Override
+ public boolean accept(final File pathname) {
+ return pathname.isFile() && accept(pathname.getName());
+ }
+
+ public static boolean accept(final String path) {
+ if (path.endsWith(".zip")) return true;
+ if (!path.endsWith("ar")) return false; // optimization
+ return path.endsWith(".jar") ||
+ path.endsWith(".ear") ||
+ path.endsWith(".war") ||
+ path.endsWith(".rar");
+ }
+ }
+}
\ No newline at end of file
diff --git a/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/MethodTransformer.java b/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/MethodTransformer.java
new file mode 100644
index 0000000..8666b34
--- /dev/null
+++ b/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/MethodTransformer.java
@@ -0,0 +1,118 @@
+/*
+ * 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 org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ConstantDynamic;
+import org.objectweb.asm.Handle;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.TypePath;
+
+public class MethodTransformer extends MethodVisitor {
+
+ public MethodTransformer(final int api, final MethodVisitor methodVisitor) {
+ super(api, methodVisitor);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotationDefault() {
+ return new AnnotationTransformer(this.api, super.visitAnnotationDefault());
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
+ return new AnnotationTransformer(this.api, super.visitAnnotation(descriptor, visible));
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ return new AnnotationTransformer(this.api, super.visitTypeAnnotation(typeRef, typePath, descriptor, visible));
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(final int parameter, final String descriptor, final boolean visible) {
+ return new AnnotationTransformer(this.api, super.visitParameterAnnotation(parameter, descriptor, visible));
+ }
+
+ @Override
+ public void visitFrame(final int type, final int numLocal, final Object[] local, final int numStack, final Object[] stack) {
+ switch (type) {
+ case -1:
+ case 0:
+// add(bytecodeUsage, local);
+// add(bytecodeUsage, stack);
+ break;
+ case 1:
+// add(bytecodeUsage, local);
+ break;
+ case 2:
+ break;
+ case 3:
+ break;
+ case 4:
+// add(bytecodeUsage, stack);
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ super.visitFrame(type, numLocal, local, numStack, stack);
+ }
+
+ @Override
+ public void visitLdcInsn(final Object cst) {
+ if (cst instanceof Integer) {
+ // ...
+ } else if (cst instanceof Float) {
+ // ...
+ } else if (cst instanceof Long) {
+ // ...
+ } else if (cst instanceof Double) {
+ // ...
+ } else if (cst instanceof String) {
+ // ...
+ } else if (cst instanceof Type) {
+ // ...
+ } else if (cst instanceof Handle) {
+ // ...
+ } else if (cst instanceof ConstantDynamic) {
+ // ...
+ } else {
+ // throw an exception
+ }
+ super.visitLdcInsn(cst);
+ }
+
+ @Override
+ public AnnotationVisitor visitInsnAnnotation(final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ return new AnnotationTransformer(this.api, super.visitInsnAnnotation(typeRef, typePath, descriptor, visible));
+ }
+
+ @Override
+ public AnnotationVisitor visitTryCatchAnnotation(final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
+ return new AnnotationTransformer(this.api, super.visitTryCatchAnnotation(typeRef, typePath, descriptor, visible));
+ }
+
+ @Override
+ public AnnotationVisitor visitLocalVariableAnnotation(final int typeRef, final TypePath typePath, final Label[] start, final Label[] end,
+ final int[] index, final String descriptor, final boolean visible) {
+ return new AnnotationTransformer(this.api, super.visitLocalVariableAnnotation(typeRef, typePath, start, end, index, descriptor, visible));
+ }
+
+
+}
diff --git a/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/ModuleTransformer.java b/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/ModuleTransformer.java
new file mode 100644
index 0000000..d295d28
--- /dev/null
+++ b/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/ModuleTransformer.java
@@ -0,0 +1,26 @@
+/*
+ * 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 org.objectweb.asm.ModuleVisitor;
+
+public class ModuleTransformer extends ModuleVisitor {
+
+ public ModuleTransformer(final int api, final ModuleVisitor moduleVisitor) {
+ super(api, moduleVisitor);
+ }
+}
diff --git a/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/SignatureTransformer.java b/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/SignatureTransformer.java
new file mode 100644
index 0000000..3112a40
--- /dev/null
+++ b/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/SignatureTransformer.java
@@ -0,0 +1,25 @@
+/*
+ * 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 org.objectweb.asm.signature.SignatureVisitor;
+
+public class SignatureTransformer extends SignatureVisitor {
+ public SignatureTransformer(final int api) {
+ super(api);
+ }
+}
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
new file mode 100644
index 0000000..8f05c8e
--- /dev/null
+++ b/tomee-patch-core/src/main/java/org/apache/tomee/patch/core/Transformation.java
@@ -0,0 +1,101 @@
+/*
+ * 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 org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Opcodes;
+import org.tomitribe.util.IO;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
+
+public class Transformation {
+
+ private Transformation() {
+ }
+
+ public static File transform(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);
+ return tempFile;
+ }
+ }
+ }
+
+ private static void scanJar(final InputStream inputStream, final OutputStream outputStream) throws IOException {
+ final ZipInputStream zipInputStream = new ZipInputStream(inputStream);
+ final ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);
+
+ ZipEntry oldEntry;
+ while ((oldEntry = zipInputStream.getNextEntry()) != null) {
+ // TODO: the name may be changed in transformation
+ final String path = oldEntry.getName();
+ final ZipEntry newEntry = new ZipEntry(path);
+
+ copyAttributes(oldEntry, newEntry);
+
+ zipOutputStream.putNextEntry(newEntry);
+
+ try {
+ if (path.endsWith(".class")) {
+ scanClass(zipInputStream, zipOutputStream);
+ } else if (isZip(path)) {
+ scanJar(zipInputStream, zipOutputStream);
+ } else {
+ IO.copy(zipInputStream, zipOutputStream);
+ }
+ } finally {
+ zipOutputStream.closeEntry();
+ }
+ }
+ zipOutputStream.close();
+ }
+
+ private static void copyAttributes(final ZipEntry oldEntry, final ZipEntry newEntry) {
+ Copy.copy(oldEntry, newEntry)
+ .att(ZipEntry::getTime, ZipEntry::setTime)
+ .att(ZipEntry::getComment, ZipEntry::setComment)
+ .att(ZipEntry::getExtra, ZipEntry::setExtra)
+ .att(ZipEntry::getMethod, ZipEntry::setMethod)
+ .att(ZipEntry::getCreationTime, ZipEntry::setCreationTime)
+ .att(ZipEntry::getLastModifiedTime, ZipEntry::setLastModifiedTime)
+ .att(ZipEntry::getLastAccessTime, ZipEntry::setLastAccessTime);
+ }
+
+ private static boolean isZip(final String path) {
+ return Is.Zip.accept(path);
+ }
+
+ private static void scanClass(final InputStream in, final OutputStream outputStream) throws IOException {
+ final ClassWriter classWriter = new ClassWriter(Opcodes.ASM8);
+ final ClassTransformer classTransformer = new ClassTransformer(classWriter);
+ final ClassReader classReader = new ClassReader(in);
+ classReader.accept(classTransformer, 0);
+ final byte[] bytes = classWriter.toByteArray();
+ outputStream.write(bytes);
+ }
+
+}
diff --git a/tomee-patch-core/src/test/java/javax/ejb/Process.java b/tomee-patch-core/src/test/java/javax/ejb/Process.java
new file mode 100644
index 0000000..0393115
--- /dev/null
+++ b/tomee-patch-core/src/test/java/javax/ejb/Process.java
@@ -0,0 +1,27 @@
+/**
+ * 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.
+ */
+//
+// This source code implements specifications defined by the Java
+// Community Process. In order to remain compliant with the specification
+// DO NOT add / change / or delete method signatures!
+//
+package javax.ejb;
+
+public class Process {
+
+ public void process(final EnterpriseBean bean) {}
+}
diff --git a/tomee-patch-core/src/test/java/javax/enterprise/context/MockScoped.java b/tomee-patch-core/src/test/java/javax/enterprise/context/MockScoped.java
new file mode 100644
index 0000000..8118d91
--- /dev/null
+++ b/tomee-patch-core/src/test/java/javax/enterprise/context/MockScoped.java
@@ -0,0 +1,41 @@
+/*
+ * 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 javax.enterprise.context;
+
+import javax.enterprise.util.AnnotationLiteral;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.TYPE, ElementType.TYPE_USE, ElementType.TYPE_PARAMETER, ElementType.METHOD, ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@NormalScope
+@Inherited
+public @interface MockScoped {
+ public static final class Literal extends AnnotationLiteral<MockScoped> implements MockScoped {
+ public static final MockScoped.Literal INSTANCE = new MockScoped.Literal();
+ private static final long serialVersionUID = 1L;
+
+ public Literal() {
+ }
+ }
+}
diff --git a/tomee-patch-core/src/test/java/javax/jms/Consumer.java b/tomee-patch-core/src/test/java/javax/jms/Consumer.java
new file mode 100644
index 0000000..7f12a84
--- /dev/null
+++ b/tomee-patch-core/src/test/java/javax/jms/Consumer.java
@@ -0,0 +1,26 @@
+/**
+ * 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.
+ */
+//
+// This source code implements specifications defined by the Java
+// Community Process. In order to remain compliant with the specification
+// DO NOT add / change / or delete method signatures!
+//
+package javax.jms;
+
+public interface Consumer<T> {
+ void accept(T t);
+}
\ No newline at end of file
diff --git a/tomee-patch-core/src/test/java/javax/jms/EnterpriseBeanConsumer.java b/tomee-patch-core/src/test/java/javax/jms/EnterpriseBeanConsumer.java
new file mode 100644
index 0000000..d7e86e4
--- /dev/null
+++ b/tomee-patch-core/src/test/java/javax/jms/EnterpriseBeanConsumer.java
@@ -0,0 +1,28 @@
+/**
+ * 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.
+ */
+//
+// This source code implements specifications defined by the Java
+// Community Process. In order to remain compliant with the specification
+// DO NOT add / change / or delete method signatures!
+//
+package javax.jms;
+
+import javax.ejb.EnterpriseBean;
+
+public interface EnterpriseBeanConsumer {
+ void accept(final EnterpriseBean bean);
+}
\ No newline at end of file
diff --git a/tomee-patch-core/src/test/java/javax/persistence/EntityBean.java b/tomee-patch-core/src/test/java/javax/persistence/EntityBean.java
new file mode 100644
index 0000000..9ec4353
--- /dev/null
+++ b/tomee-patch-core/src/test/java/javax/persistence/EntityBean.java
@@ -0,0 +1,27 @@
+/**
+ * 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.
+ */
+//
+// This source code implements specifications defined by the Java
+// Community Process. In order to remain compliant with the specification
+// DO NOT add / change / or delete method signatures!
+//
+package javax.persistence;
+
+import javax.ejb.EnterpriseBean;
+
+public interface EntityBean extends EnterpriseBean {
+}
diff --git a/tomee-patch-core/src/test/java/javax/persistence/Persist.java b/tomee-patch-core/src/test/java/javax/persistence/Persist.java
new file mode 100644
index 0000000..503c1f0
--- /dev/null
+++ b/tomee-patch-core/src/test/java/javax/persistence/Persist.java
@@ -0,0 +1,31 @@
+/**
+ * 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.
+ */
+//
+// This source code implements specifications defined by the Java
+// Community Process. In order to remain compliant with the specification
+// DO NOT add / change / or delete method signatures!
+//
+package javax.persistence;
+
+import javax.jms.Consumer;
+
+public class Persist<T> {
+
+ public void forEach(Consumer<? super T> action) {
+
+ }
+}
diff --git a/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/AnnotationTransformerTest.java b/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/AnnotationTransformerTest.java
new file mode 100644
index 0000000..1dd71b4
--- /dev/null
+++ b/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/AnnotationTransformerTest.java
@@ -0,0 +1,140 @@
+/*
+ * 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 org.junit.Test;
+import org.tomitribe.jkta.usage.Jar;
+import org.tomitribe.jkta.usage.Package;
+import org.tomitribe.jkta.usage.Usage;
+
+import javax.ejb.EnterpriseBean;
+import javax.ejb.LockType;
+import javax.servlet.http.HttpServlet;
+import javax.ws.rs.Path;
+
+import static org.apache.tomee.patch.core.Scan.assertUsage;
+import static org.apache.tomee.patch.core.Transform.usage;
+
+public class AnnotationTransformerTest {
+ // ------------------------------------------------------
+
+ @Test
+ public void visit_primitive() {
+ final Usage<Jar> usage = usage(new Object() {
+ @Data(length = 4)
+ public void get() {
+ }
+ });
+
+ assertUsage(usage);
+
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visit_String() {
+ final Usage<Jar> usage = usage(new Object() {
+ @Data(name = "javax.ejb.EnterpriseBean")
+ public void m1() {
+ }
+
+ @Data(name = "javax/ejb/EnterpriseBean")
+ public void m2() {
+ }
+
+ @Data(name = "Ljavax/ejb/EnterpriseBean")
+ public void m3() {
+ }
+ });
+
+ assertUsage(usage);
+
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visit_Class() {
+ final Usage<Jar> usage = usage(new Object() {
+ @Data(type = EnterpriseBean.class)
+ public void get() {
+ }
+ });
+
+ assertUsage(usage, Package.JAVAX_EJB);
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitEnum() {
+ final Usage<Jar> usage = usage(new Object() {
+ @Data(lock = LockType.WRITE)
+ public void get() {
+ }
+ });
+
+ assertUsage(usage, Package.JAVAX_EJB);
+
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitAnnotation() {
+ final Usage<Jar> usage = usage(new Object() {
+ @Data(path = @Path("/foo"))
+ public void get() {
+ }
+ });
+
+ assertUsage(usage, Package.JAVAX_WS_RS);
+
+ }
+ // ------------------------------------------------------
+
+ @Test
+ public void visitAnnotation_Deep() {
+ final Usage<Jar> usage = usage(new Object() {
+ @ArrayData(data = @Data(path = @Path("/foo")))
+ public void m() {
+ }
+
+ @ArrayData(data = @Data(type = HttpServlet.class))
+ public void m2() {
+ }
+ });
+
+ assertUsage(usage, Package.JAVAX_WS_RS, Package.JAVAX_SERVLET);
+
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitArray() {
+ final Usage<Jar> usage = usage(new Object() {
+ @ArrayData(data = {@Data(path = @Path("/foo")), @Data(type = HttpServlet.class)})
+ public void m() {
+ }
+ });
+
+ assertUsage(usage, Package.JAVAX_WS_RS, Package.JAVAX_SERVLET);
+ }
+
+}
diff --git a/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/ArrayData.java b/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/ArrayData.java
new file mode 100644
index 0000000..fe1a574
--- /dev/null
+++ b/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/ArrayData.java
@@ -0,0 +1,48 @@
+/*
+ * 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.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PACKAGE;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.ElementType.TYPE_PARAMETER;
+import static java.lang.annotation.ElementType.TYPE_USE;
+
+@Target({TYPE,
+ FIELD,
+ METHOD,
+ PARAMETER,
+ CONSTRUCTOR,
+ LOCAL_VARIABLE,
+ ANNOTATION_TYPE,
+ PACKAGE,
+ TYPE_PARAMETER,
+ TYPE_USE
+})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ArrayData {
+ Data[] data() default {};
+}
diff --git a/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/Asmifier.java b/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/Asmifier.java
new file mode 100644
index 0000000..1c7a26a
--- /dev/null
+++ b/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/Asmifier.java
@@ -0,0 +1,168 @@
+/*
+ * 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 org.objectweb.asm.ClassReader;
+import org.objectweb.asm.util.ASMifier;
+import org.objectweb.asm.util.TraceClassVisitor;
+import org.tomitribe.jkta.usage.Is;
+import org.tomitribe.util.Hex;
+import org.tomitribe.util.IO;
+import org.tomitribe.util.PrintString;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.UncheckedIOException;
+import java.net.URL;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+/**
+ * @version $Revision$ $Date$
+ */
+public class Asmifier {
+
+ private static final AtomicReference<File> tmpDir = new AtomicReference<File>(null);
+
+ static {
+ try {
+ final File asmifier = File.createTempFile("Asmifier", null);
+ tmpDir.set(asmifier.getParentFile());
+ if (!asmifier.delete()) {
+ asmifier.deleteOnExit();
+ }
+ } catch (final IOException e) {
+ throw new RuntimeException("Asmifier failed to locate a temporary directory");
+ }
+ }
+
+ public static void hex(final ClassLoader classLoader, final String className) throws IOException {
+ final String internalName = className.replace('.', '/') + ".class";
+ final URL resource = classLoader.getResource(internalName);
+
+ if (null == resource) {
+ throw new IOException("Failed to find resource: " + internalName);
+ }
+ System.out.println(className);
+ final InputStream inputStream = resource.openStream();
+ byte[] bytes = IO.readBytes(inputStream);
+ for (final byte b : bytes) {
+ System.out.printf("%-2s %-2s%n", Hex.toString(new byte[]{b}), (char) b);
+ }
+ }
+
+ public static void print(final ClassLoader classLoader, final String className) throws IOException {
+ final String internalName = className.replace('.', '/') + ".class";
+ final URL resource = classLoader.getResource(internalName);
+
+ if (null == resource) {
+ throw new IOException("Failed to find resource: " + internalName);
+ }
+
+ final ClassReader reader = new ClassReader(resource.openStream());
+
+
+ final File file = new File("/tmp/" + className);
+
+ write(reader, file);
+ }
+
+ private static void write(final ClassReader reader, final File file) throws IOException {
+ final OutputStream write = IO.write(file);
+ write(reader, write);
+ }
+
+ public static void write(final ClassReader reader, final OutputStream write) throws IOException {
+ final TraceClassVisitor visitor = new TraceClassVisitor(null, new ASMifier(), new PrintWriter(write));
+ reader.accept(visitor, ClassReader.SKIP_DEBUG);
+ write.close();
+ }
+
+ public static void asmify(final Class clazz, final String suffix) throws IOException {
+ asmify(clazz.getName(), Bytecode.readClassFile(clazz.getClassLoader(), clazz), suffix);
+ }
+
+ public static void asmify(final ClassLoader loader, final String className, final String suffix) throws IOException {
+ asmify(className, Bytecode.readClassFile(loader, className), suffix);
+ }
+
+ public static void asmify(final String className, final byte[] bytes, final String suffix) throws IOException {
+ final ClassReader reader = new ClassReader(bytes);
+ final File file = new File(tmpDir.get(), className + "." + suffix);
+
+ write(reader, file);
+ }
+
+ public static String asmify(final byte[] actualBytes) throws IOException {
+ final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ write(new ClassReader(actualBytes), byteArrayOutputStream);
+ return new String(byteArrayOutputStream.toByteArray());
+ }
+
+ public static String asmifyJar(final File jar) throws IOException {
+ final PrintString printString = new PrintString();
+ final InputStream read = IO.read(jar);
+ asmifyJar(read, printString);
+ return printString.toString();
+ }
+
+ private static void asmifyJar(final InputStream inputStream, final PrintStream out) throws IOException {
+ final ZipInputStream zipInputStream = new ZipInputStream(inputStream);
+
+ ZipEntry entry;
+ while ((entry = zipInputStream.getNextEntry()) != null) {
+
+ entryMetadata(entry, out);
+
+ final String path = entry.getName();
+
+ if (path.endsWith(".class")) {
+ asmifyClass(zipInputStream, out);
+ } else if (isZip(path)) {
+ asmifyJar(zipInputStream, out);
+ } else {
+ IO.copy(zipInputStream, out);
+ }
+ }
+ }
+
+ private static void entryMetadata(final ZipEntry entry, final PrintStream out) {
+ out.printf("%n-----------------------------------------------%n");
+ out.printf("name: %s%n", entry.getName());
+ out.printf("----%n");
+ }
+
+ private static void asmifyClass(final InputStream inputStream, final PrintStream out) {
+ try {
+ final byte[] bytes = IO.readBytes(inputStream);
+ final String asmify = Asmifier.asmify(bytes);
+ out.println(asmify);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
+ private static boolean isZip(final String path) {
+ return Is.Zip.accept(path);
+ }
+}
diff --git a/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/Bytecode.java b/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/Bytecode.java
new file mode 100644
index 0000000..445d528
--- /dev/null
+++ b/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/Bytecode.java
@@ -0,0 +1,62 @@
+/*
+ * 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 org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.tomitribe.util.IO;
+
+import java.io.IOException;
+import java.net.URL;
+
+/**
+ * @version $Revision$ $Date$
+ */
+public class Bytecode {
+
+ private Bytecode() {
+ // no-op
+ }
+
+ public static byte[] readClassFile(final Class clazz) throws IOException {
+ ClassLoader classLoader = clazz.getClassLoader();
+ if (classLoader == null) {
+ classLoader = Thread.currentThread().getContextClassLoader();
+ }
+ return readClassFile(classLoader, clazz);
+ }
+
+ public static byte[] readClassFile(final ClassLoader classLoader, final Class clazz) throws IOException {
+ final String internalName = clazz.getName().replace('.', '/') + ".class";
+ final URL resource = classLoader.getResource(internalName);
+ return IO.readBytes(resource);
+ }
+
+ public static byte[] readClassFile(final ClassLoader classLoader, final String className) throws IOException {
+ final String internalName = className.replace('.', '/') + ".class";
+ final URL resource = classLoader.getResource(internalName);
+ return IO.readBytes(resource);
+ }
+
+ public static void read(final byte[] originalBytes, final ClassVisitor classAdapter) {
+ if (originalBytes == null) throw new IllegalStateException("bytecode array is null");
+ final ClassReader cr = new ClassReader(originalBytes);
+ cr.accept(classAdapter, ClassReader.EXPAND_FRAMES);
+ }
+
+}
diff --git a/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/ClassTransformerTest.java b/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/ClassTransformerTest.java
new file mode 100644
index 0000000..c0ac8f4
--- /dev/null
+++ b/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/ClassTransformerTest.java
@@ -0,0 +1,285 @@
+/*
+ * 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 org.junit.Ignore;
+import org.junit.Test;
+import org.tomitribe.jkta.usage.Jar;
+import org.tomitribe.jkta.usage.Package;
+import org.tomitribe.jkta.usage.Usage;
+
+import javax.ejb.EJBException;
+import javax.ejb.EnterpriseBean;
+import javax.ejb.SessionBean;
+import javax.enterprise.context.MockScoped;
+import javax.enterprise.context.RequestScoped;
+import javax.enterprise.inject.spi.Bean;
+import javax.persistence.Persistence;
+import javax.servlet.http.HttpServlet;
+import javax.ws.rs.Path;
+import java.io.IOException;
+import java.io.Serializable;
+import java.lang.ref.Reference;
+import java.util.Set;
+
+import static org.apache.tomee.patch.core.Scan.assertUsage;
+import static org.apache.tomee.patch.core.Transform.usage;
+
+public class ClassTransformerTest {
+ // ------------------------------------------------------
+
+ @Test
+ public void visit_Negative() {
+ final Usage<Jar> usage = usage(VisitNegative.class);
+
+ assertUsage(usage);
+ }
+
+ public static class Parent {
+ }
+
+ public static interface Contract {
+ }
+
+ public static class VisitNegative extends Parent implements Serializable, Contract {
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visit_SuperClass() {
+ final Usage<Jar> usage = usage(HasSuper.class);
+
+ assertUsage(usage, Package.JAVAX_SERVLET, Package.JAVAX_SERVLET);
+
+ }
+
+ public static class HasSuper extends HttpServlet implements Serializable, Contract {
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visit_Interfaces() {
+ final Usage<Jar> usage = usage(HasInterface.class);
+
+ assertUsage(usage, Package.JAVAX_EJB);
+
+ }
+
+ public static class HasInterface implements Serializable, EnterpriseBean, Contract {
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visit_Signature() {
+ final Usage<Jar> usage = usage(HasSignature.class);
+
+ assertUsage(usage, Package.JAVAX_EJB);
+
+ }
+
+ public static class HasSignature<T extends SessionBean> {
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visit_Signature2() {
+ final Usage<Jar> usage = usage(HasSignature2.class);
+
+ assertUsage(usage, Package.JAVAX_EJB);
+
+ }
+
+ public static interface HasSignature2 extends Set<SessionBean> {
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visit_All() {
+ final Usage<Jar> usage = usage(HasAll.class);
+
+ assertUsage(usage,
+ Package.JAVAX_EJB,
+ Package.JAVAX_SERVLET,
+ Package.JAVAX_SERVLET,
+ Package.JAVAX_PERSISTENCE
+ );
+
+ }
+
+ public static interface Generic<S> {
+ }
+
+ public static class HasAll extends HttpServlet implements Serializable, EnterpriseBean, Generic<Persistence> {
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitAnnotation() {
+ final Usage<Jar> usage = usage(HasAnnotation.class);
+
+ assertUsage(usage, Package.JAVAX_ENTERPRISE);
+ }
+
+ @RequestScoped
+ public static class HasAnnotation {
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitAnnotation_Deep() {
+ final Usage<Jar> usage = usage(HasAnnotationData.class);
+
+ assertUsage(usage, Package.JAVAX_WS_RS, Package.JAVAX_SERVLET);
+ }
+
+ @ArrayData(data = {@Data(path = @Path("/foo")), @Data(type = HttpServlet.class)})
+ public static class HasAnnotationData {
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitTypeAnnotation() {
+ final Usage<Jar> usage = usage(HasTypeAnnotation.class);
+
+ assertUsage(usage, Package.JAVAX_ENTERPRISE);
+ }
+
+ public static class HasTypeAnnotation implements Generic<@MockScoped Reference> {
+ }
+
+ // ------------------------------------------------------
+
+ @Ignore
+ @Test
+ public void visitTypeAnnotation_Deep_PossibleAsmBug() {
+ final Usage<Jar> usage = usage(HasTypeAnnotationDeep.class);
+
+ assertUsage(usage, Package.JAVAX_WS_RS, Package.JAVAX_SERVLET);
+ }
+
+ public static class HasTypeAnnotationDeep implements Generic<@ArrayData(data = {@Data(path = @Path("/foo")), @Data(type = HttpServlet.class)}) Reference> {
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitField() {
+ final Usage<Jar> usage = usage(new Object() {
+ SessionBean sb;
+ });
+
+ assertUsage(usage, Package.JAVAX_EJB);
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitField_Signature1() {
+ final Usage<Jar> usage = usage(new Object() {
+ final Reference<SessionBean> sb = null;
+ });
+
+ assertUsage(usage, Package.JAVAX_EJB);
+ }
+
+ // ------------------------------------------------------
+
+ /**
+ * The "Bean" type will show up both in ASM's field descriptor
+ * and in the generic signature string. We should only count
+ * one of them.
+ */
+ @Test
+ public void visitField_SignatureNoDuplicate() {
+ final Usage<Jar> usage = usage(new Object() {
+ Bean<SessionBean> bean;
+ });
+
+ assertUsage(usage, Package.JAVAX_EJB, Package.JAVAX_ENTERPRISE);
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitMethod_Return() {
+ final Usage<Jar> usage = usage(new Object() {
+ public SessionBean get() {
+ return null;
+ }
+ });
+
+ assertUsage(usage, Package.JAVAX_EJB);
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitMethod_ReturnGeneric() {
+ final Usage<Jar> usage = usage(new Object() {
+ public Generic<SessionBean> get() {
+ return null;
+ }
+ });
+
+ assertUsage(usage, Package.JAVAX_EJB);
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitMethod_Parameter() {
+ final Usage<Jar> usage = usage(new Object() {
+ public void get(SessionBean sb) {
+ }
+ });
+
+ assertUsage(usage, Package.JAVAX_EJB);
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitMethod_ParameterGeneric() {
+ final Usage<Jar> usage = usage(new Object() {
+ public void get(Object o, Generic<SessionBean> sb, int i) {
+ }
+ });
+
+ assertUsage(usage, Package.JAVAX_EJB);
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitMethod_Throws() {
+ final Usage<Jar> usage = usage(new Object() {
+ public void get(Serializable s) throws EJBException, IOException {
+ }
+ });
+
+ assertUsage(usage, Package.JAVAX_EJB);
+ }
+
+}
diff --git a/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/Data.java b/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/Data.java
new file mode 100644
index 0000000..40ba02f
--- /dev/null
+++ b/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/Data.java
@@ -0,0 +1,35 @@
+/*
+ * 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 javax.ejb.LockType;
+import javax.ws.rs.Path;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Data {
+ int length() default 2;
+
+ String name() default "";
+
+ LockType lock() default LockType.READ;
+
+ Path path() default @Path("/");
+
+ Class type() default Object.class;
+}
diff --git a/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/FieldTransformerTest.java b/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/FieldTransformerTest.java
new file mode 100644
index 0000000..ebf85ed
--- /dev/null
+++ b/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/FieldTransformerTest.java
@@ -0,0 +1,95 @@
+/*
+ * 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 org.junit.Ignore;
+import org.junit.Test;
+import org.tomitribe.jkta.usage.Jar;
+import org.tomitribe.jkta.usage.Package;
+import org.tomitribe.jkta.usage.Usage;
+
+import javax.enterprise.context.MockScoped;
+import javax.persistence.Id;
+import javax.servlet.http.HttpServlet;
+import javax.ws.rs.Path;
+import java.util.Set;
+
+import static org.apache.tomee.patch.core.Scan.assertUsage;
+import static org.apache.tomee.patch.core.Transform.usage;
+
+public class FieldTransformerTest {
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitAnnotation() {
+ final Usage<Jar> usage = usage(new Object() {
+ @Id
+ private Object o;
+ });
+
+ assertUsage(usage, Package.JAVAX_PERSISTENCE);
+ }
+
+ // ------------------------------------------------------
+
+ @Ignore
+ @Test
+ public void visitAnnotation_Deep_PossibleAsmBug() {
+ final Usage<Jar> usage = usage(new Object() {
+ @ArrayData(data = {@Data(path = @Path("/foo")), @Data(type = HttpServlet.class)})
+ private Object o;
+ });
+
+ assertUsage(usage, Package.JAVAX_SERVLET, Package.JAVAX_WS_RS);
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitAnnotation_Deep() {
+ final Usage<Jar> usage = usage(new Object() {
+ @Data(type = HttpServlet.class)
+ private Object o;
+ });
+
+ assertUsage(usage, Package.JAVAX_SERVLET);
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitTypeAnnotation() {
+ final Usage<Jar> usage = usage(new Object() {
+ Set<@MockScoped Long> set;
+ });
+
+ assertUsage(usage, Package.JAVAX_ENTERPRISE);
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitTypeAnnotation_Deep() {
+ final Usage<Jar> usage = usage(new Object() {
+ Set<@ArrayData(data = {@Data(path = @Path("/foo")), @Data(type = HttpServlet.class)}) Long> set;
+ });
+
+ assertUsage(usage, Package.JAVAX_SERVLET, Package.JAVAX_WS_RS);
+ }
+
+}
diff --git a/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/MethodTransformerTest.java b/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/MethodTransformerTest.java
new file mode 100644
index 0000000..914d1f7
--- /dev/null
+++ b/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/MethodTransformerTest.java
@@ -0,0 +1,445 @@
+/*
+ * 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 org.junit.Ignore;
+import org.junit.Test;
+import org.objectweb.asm.Handle;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.tomitribe.jkta.usage.BytecodeUsage;
+import org.tomitribe.jkta.usage.Jar;
+import org.tomitribe.jkta.usage.MethodScanner;
+import org.tomitribe.jkta.usage.Package;
+import org.tomitribe.jkta.usage.Usage;
+
+import javax.ejb.EnterpriseBean;
+import javax.ejb.Process;
+import javax.ejb.Schedule;
+import javax.ejb.ScheduleExpression;
+import javax.ejb.SessionBean;
+import javax.enterprise.context.MockScoped;
+import javax.jms.EnterpriseBeanConsumer;
+import javax.persistence.EntityBean;
+import javax.persistence.Persist;
+import javax.persistence.PersistenceException;
+import javax.servlet.http.HttpServlet;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.Cookie;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.apache.tomee.patch.core.Scan.assertUsage;
+import static org.apache.tomee.patch.core.Transform.usage;
+
+public class MethodTransformerTest {
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitAnnotation() {
+ final Usage<Jar> usage = usage(new Object() {
+ @Schedule
+ public void get() {
+ }
+ });
+
+ assertUsage(usage, Package.JAVAX_EJB);
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitAnnotation_Deep() {
+ final Usage<Jar> usage = usage(new Object() {
+ @ArrayData(data = {@Data(path = @Path("/foo")), @Data(type = HttpServlet.class)})
+ public void get() {
+ }
+ });
+
+ assertUsage(usage, Package.JAVAX_SERVLET, Package.JAVAX_WS_RS);
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitTypeAnnotation() {
+ final Usage<Jar> usage = usage(new Object() {
+ public <@MockScoped V> V get() {
+ return null;
+ }
+ });
+
+ assertUsage(usage, Package.JAVAX_ENTERPRISE);
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitTypeAnnotation_Deep() {
+ final Usage<Jar> usage = usage(new Object() {
+ public <@ArrayData(data = {@Data(path = @Path("/foo")), @Data(type = HttpServlet.class)}) V> V get() {
+ return null;
+ }
+ });
+
+ assertUsage(usage, Package.JAVAX_SERVLET, Package.JAVAX_WS_RS);
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitParameterAnnotation() {
+ final Usage<Jar> usage = usage(new Object() {
+ public void m(@PathParam("id") int id) {
+ }
+ });
+
+ assertUsage(usage, Package.JAVAX_WS_RS);
+ }
+
+ // ------------------------------------------------------
+
+ @Ignore
+ @Test
+ public void visitParameterAnnotation_Deep_PotentialAsmBug() {
+ final Usage<Jar> usage = usage(new Object() {
+ public void m(@ArrayData(data = {@Data(path = @Path("/foo")), @Data(type = HttpServlet.class)}) int id) {
+ }
+ });
+
+ assertUsage(usage, Package.JAVAX_WS_RS, Package.JAVAX_SERVLET);
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitParameterAnnotation_Deep() {
+ final Usage<Jar> usage = usage(new Object() {
+ public void m(@Data(type = HttpServlet.class) int id) {
+ }
+ });
+
+ assertUsage(usage, Package.JAVAX_SERVLET);
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitFrame() {
+ final Usage<Jar> usage = usage(new Object() {
+ public void m(Object o) {
+ EnterpriseBean bean = (SessionBean) o;
+ try {
+ m(bean);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ });
+
+ assertUsage(usage, Package.JAVAX_EJB, Package.JAVAX_EJB);
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitTypeInsn() {
+ final Usage<Jar> usage = usage(new Object() {
+ public void m(Object o) {
+ final Object bean = (SessionBean) o;
+ System.out.println(bean);
+ }
+ });
+
+ assertUsage(usage, Package.JAVAX_EJB);
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitFieldInsn() {
+ final Usage<Jar> usage = usage(new Object() {
+ final SessionBean bean = null;
+ });
+
+ assertUsage(usage, Package.JAVAX_EJB, Package.JAVAX_EJB);
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitMethodInsn() {
+ final Usage<Jar> usage = usage(new Object() {
+
+ public void m() {
+ new ScheduleExpression();
+ }
+ });
+
+ assertUsage(usage, Package.JAVAX_EJB, Package.JAVAX_EJB);
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitMethodInsn_Descriptor() {
+ final Usage<Jar> usage = usage(new Object() {
+ public void m(final EnterpriseBeanConsumer consumer, final EntityBean bean) {
+ consumer.accept(bean);
+ }
+ });
+
+ assertUsage(usage, Package.JAVAX_JMS, Package.JAVAX_JMS, Package.JAVAX_EJB, Package.JAVAX_PERSISTENCE);
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitInvokeDynamicInsn_Direct() {
+ final Usage usage = new Usage();
+ final MethodScanner methodScanner = new MethodScanner(Opcodes.ASM8, new BytecodeUsage(usage, Opcodes.ASM8));
+ methodScanner.visitInvokeDynamicInsn(
+ "accept",
+ "(Ljavax/ejb/Process;)Ljavax/jms/Consumer;",
+ new Handle(Opcodes.H_INVOKESTATIC,
+ "java/lang/invoke/LambdaMetafactory",
+ "metafactory",
+ "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;",
+ false),
+ new Object[]{
+ Type.getType("(Ljava/lang/Object;)V"),
+ new Handle(Opcodes.H_INVOKEVIRTUAL,
+ "javax/ejb/Process",
+ "process",
+ "(Ljavax/ejb/EnterpriseBean;)V",
+ false),
+ Type.getType("(Ljavax/ejb/EnterpriseBean;)V")
+ }
+ );
+
+ assertUsage(usage,
+ Package.JAVAX_EJB,
+ Package.JAVAX_EJB,
+ Package.JAVAX_EJB,
+ Package.JAVAX_EJB,
+ Package.JAVAX_JMS
+ );
+
+ }
+
+ @Test
+ public void visitInvokeDynamicInsn() {
+ final Usage<Jar> usage = usage(new Object() {
+ public void invokedynamic(Persist<EnterpriseBean> persist, Process process) {
+ persist.forEach(process::process);
+ }
+ });
+
+ assertUsage(usage,
+ Package.JAVAX_PERSISTENCE, // visitMethod
+ Package.JAVAX_EJB, // visitMethod
+ Package.JAVAX_EJB, // visitMethod
+ Package.JAVAX_EJB, // visitInvokeDynamicInsn
+ Package.JAVAX_EJB, // visitInvokeDynamicInsn
+ Package.JAVAX_EJB, // visitInvokeDynamicInsn
+ Package.JAVAX_EJB, // visitInvokeDynamicInsn
+ Package.JAVAX_JMS, // visitInvokeDynamicInsn
+ Package.JAVAX_PERSISTENCE, // visitMethodInsn
+ Package.JAVAX_JMS // visitMethodInsn
+ );
+
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitLdcInsn_Type() {
+ final Usage<Jar> usage = usage(new Object() {
+ public void m() {
+ System.out.println(GET.class);
+ }
+ });
+
+ assertUsage(usage,
+ Package.JAVAX_WS_RS
+ );
+ }
+
+ // ------------------------------------------------------
+
+ /**
+ * TODO This is a stub. Real test needed.
+ */
+ @Ignore("https://github.com/tomitribe/jkta/issues/2")
+ @Test
+ public void visitLdcInsn_Handle() {
+ }
+
+ // ------------------------------------------------------
+
+
+ /**
+ * TODO This is a stub. Real test needed.
+ */
+ @Ignore("https://github.com/tomitribe/jkta/issues/3")
+ @Test
+ public void visitLdcInsn_ConstantDynamic() {
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitMultiANewArrayInsn() {
+ final Usage<Jar> usage = usage(new Object() {
+ public void m() {
+ final Cookie[][][] cookies = new Cookie[4][8][16];
+ }
+ });
+
+ assertUsage(usage,
+ Package.JAVAX_WS_RS
+ );
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitInsnAnnotation() {
+ final Usage<Jar> usage = usage(new Object() {
+ public void m() {
+ final List list = (@MockScoped ArrayList) null;
+ }
+ });
+
+ assertUsage(usage,
+ Package.JAVAX_ENTERPRISE
+ );
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitInsnAnnotation_Deep() {
+ final Usage<Jar> usage = usage(new Object() {
+ public void m() {
+ final List list = (@ArrayData(data = {@Data(path = @Path("/foo")), @Data(type = HttpServlet.class)}) ArrayList) null;
+ }
+ });
+
+ assertUsage(usage,
+ Package.JAVAX_SERVLET,
+ Package.JAVAX_WS_RS
+ );
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitTryCatchBlock() {
+ final Usage<Jar> usage = usage(new Object() {
+ public void m() {
+ try {
+ System.out.println();
+ } catch (PersistenceException e) {
+ System.out.println();
+ }
+ }
+ });
+
+ assertUsage(usage,
+ Package.JAVAX_PERSISTENCE, // visitTryCatchBlock
+ Package.JAVAX_PERSISTENCE // visitFrame
+ );
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitTryCatchAnnotation() {
+ final Usage<Jar> usage = usage(new Object() {
+ public void m() {
+ try {
+ System.out.println();
+ } catch (@MockScoped PersistenceException e) {
+ System.out.println();
+ }
+ }
+ });
+
+ assertUsage(usage,
+ Package.JAVAX_ENTERPRISE, // visitTryCatchBlock
+ Package.JAVAX_PERSISTENCE, // visitTryCatchBlock
+ Package.JAVAX_PERSISTENCE // visitFrame
+ );
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitTryCatchAnnotation_Deep() {
+ final Usage<Jar> usage = usage(new Object() {
+ public void m() {
+ try {
+ System.out.println();
+ } catch (@ArrayData(data = {@Data(path = @Path("/foo")), @Data(type = HttpServlet.class)}) PersistenceException e) {
+ System.out.println();
+ }
+ }
+ });
+
+ assertUsage(usage,
+ Package.JAVAX_SERVLET,
+ Package.JAVAX_WS_RS,
+ Package.JAVAX_PERSISTENCE,
+ Package.JAVAX_PERSISTENCE
+ );
+ }
+
+ // ------------------------------------------------------
+
+ @Test
+ public void visitLocalVariableAnnotation() {
+ final Usage<Jar> usage = usage(new Object() {
+ public void m() {
+ @MockScoped long e = System.nanoTime();
+ }
+ });
+
+ assertUsage(usage,
+ Package.JAVAX_ENTERPRISE
+ );
+ }
+ // ------------------------------------------------------
+
+ @Test
+ public void visitLocalVariableAnnotation_Deep() {
+ final Usage<Jar> usage = usage(new Object() {
+ public void m() {
+ @ArrayData(data = {@Data(path = @Path("/foo")), @Data(type = HttpServlet.class)}) long e = System.nanoTime();
+ }
+ });
+
+ assertUsage(usage,
+ Package.JAVAX_SERVLET,
+ Package.JAVAX_WS_RS
+ );
+ }
+
+}
diff --git a/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/ModuleTransformerTest.java b/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/ModuleTransformerTest.java
new file mode 100644
index 0000000..6df77e1
--- /dev/null
+++ b/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/ModuleTransformerTest.java
@@ -0,0 +1,21 @@
+/*
+ * 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 ModuleTransformerTest {
+
+}
diff --git a/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/Scan.java b/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/Scan.java
new file mode 100644
index 0000000..db482b2
--- /dev/null
+++ b/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/Scan.java
@@ -0,0 +1,70 @@
+/*
+ * 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 org.tomitribe.jkta.usage.Jar;
+import org.tomitribe.jkta.usage.JarUsage;
+import org.tomitribe.jkta.usage.Package;
+import org.tomitribe.jkta.usage.Usage;
+import org.tomitribe.util.Archive;
+
+import java.io.File;
+import java.io.IOException;
+import java.security.NoSuchAlgorithmException;
+
+import static org.junit.Assert.assertEquals;
+
+public class Scan {
+ private Scan() {
+ }
+
+ public static Usage<Jar> usage(final Object o) {
+ return usage(o.getClass());
+ }
+
+ public static Usage<Jar> usage(final Class<?> aClass) {
+ try {
+// final ClassLoader loader = aClass.getClassLoader();
+// System.out.println(Asmifier.asmify(Bytecode.readClassFile(loader, aClass)));
+// System.out.println();
+ final File jar = Archive.archive().add(aClass).toJar();
+ return JarUsage.of(jar);
+ } catch (IOException | NoSuchAlgorithmException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static void assertUsage(final Usage<Jar> usage, final Package... expectedUses) {
+ int javax = 0;
+ int jakarta = 0;
+ int[] uses = new int[Package.values().length];
+
+ for (final Package use : expectedUses) {
+ uses[use.ordinal()]++;
+ if (use.getName().startsWith("javax.")) javax++;
+ if (use.getName().startsWith("jakarta.")) jakarta++;
+ }
+
+ for (int i = 0; i < uses.length; i++) {
+ final Package pkg = Package.values()[i];
+ assertEquals(pkg.getName(), uses[i], usage.get(pkg));
+ }
+
+ assertEquals(javax, usage.getJavax());
+ assertEquals(jakarta, usage.getJakarta());
+ }
+}
diff --git a/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/SignatureTransformerTest.java b/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/SignatureTransformerTest.java
new file mode 100644
index 0000000..7a62a79
--- /dev/null
+++ b/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/SignatureTransformerTest.java
@@ -0,0 +1,38 @@
+/*
+ * 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 org.junit.Test;
+
+public class SignatureTransformerTest {
+
+ @Test
+ public void visitArrayType() {
+ }
+
+ @Test
+ public void visitClassType() {
+ }
+
+ @Test
+ public void visitInnerClassType() {
+ }
+
+ @Test
+ public void visitTypeArgument() {
+ }
+}
diff --git a/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/Transform.java b/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/Transform.java
new file mode 100644
index 0000000..f3fdfa3
--- /dev/null
+++ b/tomee-patch-core/src/test/java/org/apache/tomee/patch/core/Transform.java
@@ -0,0 +1,78 @@
+/*
+ * 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 org.junit.Assert;
+import org.tomitribe.jkta.usage.Jar;
+import org.tomitribe.jkta.usage.JarUsage;
+import org.tomitribe.jkta.usage.Usage;
+import org.tomitribe.util.Archive;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.security.NoSuchAlgorithmException;
+import java.util.stream.Stream;
+
+public class Transform {
+ private Transform() {
+ }
+
+ public static Usage<Jar> usage(final Object o) {
+ return usage(o.getClass());
+ }
+
+ public static Usage<Jar> usage(final Class<?> aClass) {
+ try {
+ final File jar = new TestArchive().add(aClass).toJar();
+
+ final Usage<Jar> usageBefore = JarUsage.of(jar);
+
+ final File transformed = Transformation.transform(jar);
+
+ final String contentsBefore = Asmifier.asmifyJar(jar);
+ final String contentsAfter = Asmifier.asmifyJar(transformed);
+
+ Assert.assertEquals(contentsBefore, contentsAfter);
+
+ return JarUsage.of(transformed);
+ } catch (IOException | NoSuchAlgorithmException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static class TestArchive extends Archive {
+ public Archive add(final Class<?> clazz) {
+ try {
+ final String name = clazz.getName().replace('.', '/') + ".class";
+
+ final URL resource = this.getClass().getClassLoader().getResource(name);
+ if (resource == null) throw new IllegalStateException("Cannot find class file for " + clazz.getName());
+ add(name, resource);
+
+ // Add any anonymous nested classes
+ Stream.of(clazz.getDeclaredClasses())
+ .filter(Class::isAnonymousClass)
+ .forEach(this::add);
+
+ return this;
+ } catch (final IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+}
diff --git a/tomee-patch-plugin/pom.xml b/tomee-patch-plugin/pom.xml
index 5ed2fb9..f68116a 100644
--- a/tomee-patch-plugin/pom.xml
+++ b/tomee-patch-plugin/pom.xml
@@ -31,5 +31,93 @@
<artifactId>tomee-patch-plugin</artifactId>
<packaging>maven-plugin</packaging>
+ <properties>
+ <maven.version>3.2.2</maven.version>
+ <maven-plugin.prefix>transform</maven-plugin.prefix>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.plugin-tools</groupId>
+ <artifactId>maven-plugin-annotations</artifactId>
+ <version>3.3</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-utils</artifactId>
+ <version>3.0.17</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-plugin-api</artifactId>
+ <version>${maven.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-model</artifactId>
+ <version>${maven.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-core</artifactId>
+ <version>${maven.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-cli</groupId>
+ <artifactId>commons-cli</artifactId>
+ <version>1.4</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-artifact</artifactId>
+ <version>${maven.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-compat</artifactId>
+ <version>${maven.version}</version>
+ </dependency>
+
+ <!-- TESTS -->
+ <dependency>
+ <groupId>org.apache.maven.plugin-testing</groupId>
+ <artifactId>maven-plugin-testing-harness</artifactId>
+ <version>3.2.0</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-aether-provider</artifactId>
+ <version>${maven.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.11</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.shrinkwrap</groupId>
+ <artifactId>shrinkwrap-api</artifactId>
+ <version>1.2.6</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.shrinkwrap</groupId>
+ <artifactId>shrinkwrap-impl-base</artifactId>
+ <version>1.2.6</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax</groupId>
+ <artifactId>javaee-api</artifactId>
+ <version>8.0.1</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
</project>
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
new file mode 100644
index 0000000..27c06ad
--- /dev/null
+++ b/tomee-patch-plugin/src/main/java/org/apache/tomee/patch/plugin/TransformMojo.java
@@ -0,0 +1,33 @@
+/*
+ * 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 {
+
+ }
+}