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 <[email protected]> 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 { + + } +}
