This is an automated email from the ASF dual-hosted git repository.
struberg pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/openjpa.git
The following commit(s) were added to refs/heads/master by this push:
new 6eeb025cf OPENJPA-2911 migrate InterfaceImplGenerator wip
6eeb025cf is described below
commit 6eeb025cf3e771da8461633813e1926d912d2aab
Author: Mark Struberg <[email protected]>
AuthorDate: Wed Jul 19 17:25:52 2023 +0200
OPENJPA-2911 migrate InterfaceImplGenerator wip
Still not really there. There is still some very weirdo
ClassLoader mixup which gets 'fixed' as sideeffect of using a roundtrip to
BCClass.
Not yet 100% sure yet, still digging
---
.../org/apache/openjpa/enhance/PCEnhancer.java | 58 ++---
.../apache/openjpa/enhance/SerpPrivacyHelper.java | 37 ---
.../openjpa/meta/InterfaceImplGenerator.java | 122 +++++-----
.../org/apache/openjpa/util/asm/AsmHelper.java | 63 +++---
.../openjpa/util/asm/EnhancementClassLoader.java | 10 -
.../openjpa/util/asm/EnhancementProject.java | 2 -
.../openjpa/enhance/TestSubclassValidator.java | 9 +-
.../openjpa/persistence/test/ClassSelector.java | 247 ---------------------
8 files changed, 115 insertions(+), 433 deletions(-)
diff --git
a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java
b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java
index bf852f34a..c3ebe76f8 100644
--- a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java
+++ b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java
@@ -849,7 +849,7 @@ public class PCEnhancer {
// default: throw new IllegalArgumentException ()
instructions.add(defLbl);
- instructions.add(throwException(IllegalArgumentException.class));
+
instructions.add(AsmHelper.throwException(IllegalArgumentException.class));
}
else {
// In mixed access mode, property indexes are not +1 incremental
@@ -1401,7 +1401,7 @@ public class PCEnhancer {
final InsnList instructions = newInstance.instructions;
if ((pc.getClassNode().access & Opcodes.ACC_ABSTRACT) > 0) {
- instructions.add(throwException(USEREXCEP));
+ instructions.add(AsmHelper.throwException(USEREXCEP));
return;
}
@@ -1503,7 +1503,7 @@ public class PCEnhancer {
FieldMetaData[] fmds = getCreateSubclass() ? _meta.getFields()
: _meta.getDeclaredFields();
if (fmds.length == 0) {
- instructions.add(throwException(IllegalArgumentException.class));
+
instructions.add(AsmHelper.throwException(IllegalArgumentException.class));
}
else {
// switch (val)
@@ -1542,7 +1542,7 @@ public class PCEnhancer {
}
instructions.add(defaultCase);
- instructions.add(throwException(IllegalArgumentException.class));
+
instructions.add(AsmHelper.throwException(IllegalArgumentException.class));
}
addMultipleFieldsMethodVersion(classNode, provideFieldsMeth, false);
@@ -1565,7 +1565,7 @@ public class PCEnhancer {
FieldMetaData[] fmds = getCreateSubclass() ? _meta.getFields()
: _meta.getDeclaredFields();
if (fmds.length == 0) {
- instructions.add(throwException(IllegalArgumentException.class));
+
instructions.add(AsmHelper.throwException(IllegalArgumentException.class));
}
else {
// switch (val)
@@ -1614,7 +1614,7 @@ public class PCEnhancer {
}
instructions.add(defaultCase);
- instructions.add(throwException(IllegalArgumentException.class));
+
instructions.add(AsmHelper.throwException(IllegalArgumentException.class));
}
addMultipleFieldsMethodVersion(classNode, replaceFieldMeth, false);
@@ -1639,7 +1639,7 @@ public class PCEnhancer {
FieldMetaData[] fmds = getCreateSubclass() ? _meta.getFields()
: _meta.getDeclaredFields();
if (fmds.length == 0) {
- instructions.add(throwException(IllegalArgumentException.class));
+
instructions.add(AsmHelper.throwException(IllegalArgumentException.class));
}
else {
instructions.add(new VarInsnNode(Opcodes.ILOAD, relLocal));
@@ -1666,7 +1666,7 @@ public class PCEnhancer {
}
instructions.add(defaultCase);
- instructions.add(throwException(IllegalArgumentException.class));
+
instructions.add(AsmHelper.throwException(IllegalArgumentException.class));
}
addMultipleFieldsMethodVersion(classNode, copyFieldMeth, true);
@@ -1719,7 +1719,7 @@ public class PCEnhancer {
instructions.add(new InsnNode(Opcodes.RETURN));
}
else {
- instructions.add(throwException(IllegalArgumentException.class));
+
instructions.add(AsmHelper.throwException(IllegalArgumentException.class));
}
instructions.add(afterRelCheck);
@@ -1798,7 +1798,7 @@ public class PCEnhancer {
instructions.add(new FieldInsnNode(Opcodes.GETFIELD,
classNode.name, SM, Type.getDescriptor(SMTYPE)));
LabelNode toEndSmCmp = new LabelNode();
instructions.add(new JumpInsnNode(Opcodes.IF_ACMPEQ, toEndSmCmp));
- instructions.add(throwException(IllegalArgumentException.class));
+
instructions.add(AsmHelper.throwException(IllegalArgumentException.class));
instructions.add(toEndSmCmp);
// if (pcStateManager == null)
@@ -1807,7 +1807,7 @@ public class PCEnhancer {
instructions.add(new FieldInsnNode(Opcodes.GETFIELD,
classNode.name, SM, Type.getDescriptor(SMTYPE)));
LabelNode toEndSmNull = new LabelNode();
instructions.add(new JumpInsnNode(Opcodes.IFNONNULL, toEndSmNull));
- instructions.add(throwException(IllegalStateException.class));
+
instructions.add(AsmHelper.throwException(IllegalStateException.class));
instructions.add(toEndSmNull);
}
@@ -2179,7 +2179,7 @@ public class PCEnhancer {
// single field identity always throws exception
if (_meta.isOpenJPAIdentity()) {
- instructions.add(throwException(INTERNEXCEP));
+ instructions.add(AsmHelper.throwException(INTERNEXCEP));
return;
}
@@ -3078,7 +3078,7 @@ public class PCEnhancer {
// throw new IllegalArgumentException (...);
String msg = _loc.get("str-cons", oidType,
_meta.getDescribedType()).getMessage();
- instructions.add(throwException(IllegalArgumentException.class,
msg));
+
instructions.add(AsmHelper.throwException(IllegalArgumentException.class, msg));
return;
}
@@ -3247,38 +3247,6 @@ public class PCEnhancer {
}
}
-
- /**
- * Helper method to add the code necessary to throw the given
- * exception type, sans message.
- */
- private InsnList throwException(Class type) {
- return throwException(type, null);
- }
-
- /**
- * Helper method to add the code necessary to throw the given
- * exception type, sans message.
- */
- private InsnList throwException(Class type, String msg) {
- InsnList instructions = new InsnList();
- instructions.add(new TypeInsnNode(Opcodes.NEW,
Type.getInternalName(type)));
- instructions.add(new InsnNode(Opcodes.DUP));
- if (msg != null) {
- instructions.add(AsmHelper.getLoadConstantInsn(msg));
- }
- String desc = msg != null
- ? Type.getMethodDescriptor(Type.VOID_TYPE,
Type.getType(String.class))
- : Type.getMethodDescriptor(Type.VOID_TYPE);
- instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL,
- Type.getInternalName(type),
- "<init>",
- desc));
- instructions.add(new InsnNode(Opcodes.ATHROW));
-
- return instructions;
- }
-
/**
* Adds the PersistenceCapable interface to the class being
* enhanced, and adds a default constructor for use by OpenJPA
diff --git
a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/SerpPrivacyHelper.java
b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/SerpPrivacyHelper.java
index 7ffdab287..5e984e3cf 100644
---
a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/SerpPrivacyHelper.java
+++
b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/SerpPrivacyHelper.java
@@ -20,9 +20,7 @@ import java.security.PrivilegedAction;
import org.apache.openjpa.lib.util.J2DoPrivHelper;
-import serp.bytecode.BCClass;
import serp.bytecode.BCClassLoader;
-import serp.bytecode.BCField;
import serp.bytecode.Project;
/**
@@ -59,39 +57,4 @@ public class SerpPrivacyHelper extends J2DoPrivHelper {
};
}
- /**
- * Return a PrivilegeAction object for BCClass.getFields().
- *
- * Requires security policy:
- * 'permission java.lang.RuntimePermission "getClassLoader";'
- *
- * @return BCField
- */
- public static PrivilegedAction<BCField[]> getBCClassFieldsAction(
- final BCClass bcClass, final String fieldName) {
- return new PrivilegedAction<BCField []>() {
- @Override
- public BCField [] run() {
- return bcClass.getFields(fieldName);
- }
- };
- }
-
- /**
- * Return a PrivilegeAction object for Project.loadClass().
- *
- * Requires security policy:
- * 'permission java.lang.RuntimePermission "createClassLoader";'
- *
- * @return BCClass
- */
- public static PrivilegedAction<BCClass> loadProjectClassAction(
- final Project project, final Class<?> clazz) {
- return new PrivilegedAction<BCClass>() {
- @Override
- public BCClass run() {
- return project.loadClass(clazz);
- }
- };
- }
}
diff --git
a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/InterfaceImplGenerator.java
b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/InterfaceImplGenerator.java
index 07fc7ee80..f6410eeb2 100644
---
a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/InterfaceImplGenerator.java
+++
b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/InterfaceImplGenerator.java
@@ -35,13 +35,16 @@ import org.apache.openjpa.util.asm.AsmHelper;
import org.apache.openjpa.util.asm.ClassNodeTracker;
import org.apache.openjpa.util.asm.EnhancementClassLoader;
import org.apache.openjpa.util.asm.EnhancementProject;
+import org.apache.xbean.asm9.Opcodes;
import org.apache.xbean.asm9.Type;
+import org.apache.xbean.asm9.tree.ClassNode;
+import org.apache.xbean.asm9.tree.FieldInsnNode;
+import org.apache.xbean.asm9.tree.FieldNode;
+import org.apache.xbean.asm9.tree.InsnNode;
+import org.apache.xbean.asm9.tree.MethodNode;
+import org.apache.xbean.asm9.tree.VarInsnNode;
import serp.bytecode.BCClass;
-import serp.bytecode.BCField;
-import serp.bytecode.BCMethod;
-import serp.bytecode.Code;
-import serp.bytecode.Constants;
import serp.bytecode.Project;
/**
@@ -90,32 +93,30 @@ class InterfaceImplGenerator {
ClassMetaData sup = meta.getPCSuperclassMetaData();
if (sup != null) {
bc.getClassNode().superName =
Type.getInternalName(sup.getInterfaceImpl());
- //X enhLoader = new EnhancementClassLoader(_enhProject,
sup.getInterfaceImpl().getClassLoader());
+ enhLoader = new EnhancementClassLoader(_enhProject,
sup.getInterfaceImpl().getClassLoader());
}
FieldMetaData[] fields = meta.getDeclaredFields();
Set<Method> methods = new HashSet<>();
- //X TODO REMOVE
- BCClass _bc = new Project().loadClass(getClassName(meta));
- AsmHelper.readIntoBCClass(bc, _bc);
-
for (FieldMetaData field : fields) {
- addField(_bc, iface, field, methods);
+ addField(bc, iface, field, methods);
}
- invalidateNonBeanMethods(_bc, iface, methods);
+ invalidateNonBeanMethods(bc, iface, methods);
// first load the base Class<?> as the enhancer requires the class
// to be available
try {
- meta.setInterfaceImpl(Class.forName(_bc.getName(), true, loader));
+
meta.setInterfaceImpl(Class.forName(bc.getClassNode().name.replace("/", "."),
true, loader));
} catch (Throwable t) {
- throw new InternalException(_loc.get("interface-load", iface,
- loader), t).setFatal(true);
+ throw new InternalException(_loc.get("interface-load", iface,
loader), t).setFatal(true);
}
// copy the BCClass<?> into the enhancer project.
//X bc = _enhProject.loadClass(new
ByteArrayInputStream(_bc.toByteArray()), loader);
+ //X TODO REMOVE
+ BCClass _bc = new Project().loadClass(getClassName(meta));
+ AsmHelper.readIntoBCClass(bc, _bc);
ClassNodeTracker bcEnh = AsmHelper.toClassNode(_enhProject, _bc);
PCEnhancer enhancer = new PCEnhancer(_repos, bcEnh, meta);
@@ -125,8 +126,14 @@ class InterfaceImplGenerator {
iface)).setFatal(true);
try {
// load the Class<?> for real.
+ EnhancementProject finalProject = new EnhancementProject();
+ EnhancementClassLoader finalLoader = new
EnhancementClassLoader(finalProject, parentLoader);
+ final byte[] classBytes2 =
AsmHelper.toByteArray(enhancer.getPCBytecode());
+ ClassNodeTracker bcEnh2 = finalProject.loadClass(classBytes2,
finalLoader);
+
String pcClassName =
enhancer.getPCBytecode().getClassNode().name.replace("/", ".");
- impl = Class.forName(pcClassName, true, enhLoader);
+ impl = Class.forName(pcClassName, true, finalLoader);
+
} catch (Throwable t) {
//X throw new InternalException(_loc.get("interface-load2", iface,
enhLoader), t).setFatal(true);
throw new InternalException(_loc.get("interface-load2", iface,
loader), t).setFatal(true);
@@ -140,63 +147,58 @@ class InterfaceImplGenerator {
* Add bean getters and setters, also recording seen methods
* into the given set.
*/
- private void addField (BCClass bc, Class<?> iface, FieldMetaData fmd,
- Set<Method> methods) {
- String name = fmd.getName();
+ private void addField (ClassNodeTracker cnt, Class<?> iface, FieldMetaData
fmd, Set<Method> methods) {
+ final ClassNode classNode = cnt.getClassNode();
+ String fieldName = fmd.getName();
Class<?> type = fmd.getDeclaredType();
- BCField field = bc.declareField(name, type);
- field.setAccessFlags(Constants.ACCESS_PRIVATE);
+ FieldNode field = new FieldNode(Opcodes.ACC_PRIVATE, fieldName,
Type.getDescriptor(type), null, null);
+ classNode.fields.add(field);
// getter
- name = StringUtil.capitalize(name);
- String prefix = isGetter(iface, fmd) ? "get" : "is";
- BCMethod meth = bc.declareMethod(prefix + name, type, null);
- meth.makePublic();
- Code code = meth.getCode(true);
- code.aload().setThis();
- code.getfield().setField(field);
- code.xreturn().setType(type);
- code.calculateMaxStack();
- code.calculateMaxLocals();
- methods.add(getMethodSafe(iface, meth.getName(), null));
+ String getterName = (isGetter(iface, fmd) ? "get" : "is") +
StringUtil.capitalize(fieldName);
+ MethodNode meth = new MethodNode(Opcodes.ACC_PUBLIC,
+ getterName,
+
Type.getMethodDescriptor(Type.getType(type)),
+ null, null);
+ classNode.methods.add(meth);
+ meth.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
+ meth.instructions.add(new FieldInsnNode(Opcodes.GETFIELD,
classNode.name, fieldName, Type.getDescriptor(type)));
+ meth.instructions.add(new InsnNode(AsmHelper.getReturnInsn(type)));
+ methods.add(getMethodSafe(iface, meth.name, null));
// setter
- meth = bc.declareMethod("set" + name, void.class, new Class[]{type});
- meth.makePublic();
- code = meth.getCode(true);
- code.aload().setThis();
- code.xload().setParam(0).setType(type);
- code.putfield().setField(field);
- code.vreturn();
- code.calculateMaxStack();
- code.calculateMaxLocals();
- methods.add(getMethodSafe(iface, meth.getName(), type));
+ String setterName = "set" + StringUtil.capitalize(fieldName);
+ meth = new MethodNode(Opcodes.ACC_PUBLIC,
+ setterName,
+ Type.getMethodDescriptor(Type.VOID_TYPE,
Type.getType(type)),
+ null, null);
+ classNode.methods.add(meth);
+ meth.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
+ meth.instructions.add(new VarInsnNode(AsmHelper.getLoadInsn(type),
1)); // 1st parameter
+ meth.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD,
classNode.name, fieldName, Type.getDescriptor(type)));
+ meth.instructions.add(new InsnNode(Opcodes.RETURN));
+ methods.add(getMethodSafe(iface, meth.name, type));
}
/**
* Invalidate methods on the interface which are not managed.
*/
- private void invalidateNonBeanMethods(BCClass bc, Class<?> iface,
- Set<Method> methods) {
- Method[] meths = (Method[]) AccessController.doPrivileged(
- J2DoPrivHelper.getDeclaredMethodsAction(iface));
- BCMethod meth;
- Code code;
- Class<?> type = _repos.getMetaDataFactory().getDefaults().
- getUnimplementedExceptionType();
+ private void invalidateNonBeanMethods(ClassNodeTracker cnt, Class<?>
iface, Set<Method> methods) {
+ Method[] meths =
AccessController.doPrivileged(J2DoPrivHelper.getDeclaredMethodsAction(iface));
+
+
+ Class<?> unimplementedExceptionType =
_repos.getMetaDataFactory().getDefaults().getUnimplementedExceptionType();
+
for (Method method : meths) {
- if (methods.contains(method))
+ if (methods.contains(method)) {
continue;
- meth = bc.declareMethod(method.getName(),
- method.getReturnType(), method.getParameterTypes());
- meth.makePublic();
- code = meth.getCode(true);
- code.anew().setType(type);
- code.dup();
- code.invokespecial().setMethod(type, "<init>", void.class, null);
- code.athrow();
- code.calculateMaxLocals();
- code.calculateMaxStack();
+ }
+ MethodNode methodNode = new MethodNode(Opcodes.ACC_PUBLIC,
+ method.getName(),
+
Type.getMethodDescriptor(method),
+ null, null);
+
methodNode.instructions.add(AsmHelper.throwException(unimplementedExceptionType));
+ cnt.getClassNode().methods.add(methodNode);
}
}
diff --git
a/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/AsmHelper.java
b/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/AsmHelper.java
index 0e1b007fe..d1ec64140 100644
--- a/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/AsmHelper.java
+++ b/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/AsmHelper.java
@@ -34,14 +34,16 @@ import org.apache.xbean.asm9.Type;
import org.apache.xbean.asm9.tree.AbstractInsnNode;
import org.apache.xbean.asm9.tree.ClassNode;
import org.apache.xbean.asm9.tree.FieldInsnNode;
+import org.apache.xbean.asm9.tree.InsnList;
import org.apache.xbean.asm9.tree.InsnNode;
import org.apache.xbean.asm9.tree.IntInsnNode;
import org.apache.xbean.asm9.tree.LdcInsnNode;
+import org.apache.xbean.asm9.tree.MethodInsnNode;
import org.apache.xbean.asm9.tree.MethodNode;
+import org.apache.xbean.asm9.tree.TypeInsnNode;
import org.apache.xbean.asm9.tree.VarInsnNode;
import serp.bytecode.BCClass;
-import serp.bytecode.Project;
/**
* Utility methods to deal with ASM bytecode
@@ -100,21 +102,6 @@ public final class AsmHelper {
return classNode;
}
- /**
- * temporary helper class to convert BCClass to ASM ClassWriter
- * @deprecated must get removed when done with migrating from Serp to ASM
- */
- public static ClassWriterTracker toClassWriter(BCClass bcClass) {
- ClassReader cr = new ClassReader(bcClass.toByteArray());
- ClassWriter cw = new BCClassWriter(ClassWriter.COMPUTE_FRAMES,
bcClass.getClassLoader());
- cr.accept(cw, ATTRS, 0); // 0 -> don't skip anything
- ClassWriterTracker cwt = new ClassWriterTracker(cw,
bcClass.getClassLoader());
- cwt.setName(bcClass.getName());
-
- return cwt;
- }
-
-
public static byte[] getClassBytes(final String typeName)
{
final ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
@@ -149,17 +136,6 @@ public final class AsmHelper {
return cw.toByteArray();
}
- /**
- * temporary helper class to convert ClassWriterTracker to BCClass
- * @deprecated must get removed when done with migrating from Serp to ASM
- */
- public static BCClass toBCClass(ClassWriterTracker cwt) {
- final byte[] classBytes = cwt.getCw().toByteArray();
- BCClass bcClass = new Project().loadClass(new
ByteArrayInputStream(classBytes), cwt.getClassLoader());
- bcClass.setName(cwt.getName());
- return bcClass;
- }
-
/**
* temporary helper class to convert BCClass to ASM ClassNode
* @deprecated must get removed when done with migrating from Serp to ASM
@@ -689,6 +665,39 @@ public final class AsmHelper {
}
}
+
+ /**
+ * Helper method to add the code necessary to throw the given
+ * exception type, sans message.
+ */
+ public static InsnList throwException(Class type) {
+ return throwException(type, null);
+ }
+
+ /**
+ * Helper method to add the code necessary to throw the given
+ * exception type, sans message.
+ */
+ public static InsnList throwException(Class type, String msg) {
+ InsnList instructions = new InsnList();
+ instructions.add(new TypeInsnNode(Opcodes.NEW,
Type.getInternalName(type)));
+ instructions.add(new InsnNode(Opcodes.DUP));
+ if (msg != null) {
+ instructions.add(AsmHelper.getLoadConstantInsn(msg));
+ }
+ String desc = msg != null
+ ? Type.getMethodDescriptor(Type.VOID_TYPE,
Type.getType(String.class))
+ : Type.getMethodDescriptor(Type.VOID_TYPE);
+ instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL,
+ Type.getInternalName(type),
+ "<init>",
+ desc));
+ instructions.add(new InsnNode(Opcodes.ATHROW));
+
+ return instructions;
+ }
+
+
public static Class<?> getClass(ClassLoader classLoader, String
internalTypeName) {
try {
return Class.forName(internalTypeName.replace("/", "."), false,
classLoader);
diff --git
a/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/EnhancementClassLoader.java
b/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/EnhancementClassLoader.java
index 462eabc13..c58cecb91 100644
---
a/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/EnhancementClassLoader.java
+++
b/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/EnhancementClassLoader.java
@@ -41,16 +41,6 @@ public class EnhancementClassLoader extends ClassLoader {
return project;
}
- @Override
- public Class<?> loadClass(String name) throws ClassNotFoundException {
- return super.loadClass(name);
- }
-
- @Override
- protected Class<?> loadClass(String name, boolean resolve) throws
ClassNotFoundException {
- return super.loadClass(name, resolve);
- }
-
protected Class findClass(String name) throws ClassNotFoundException {
byte[] bytes;
try {
diff --git
a/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/EnhancementProject.java
b/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/EnhancementProject.java
index de93f1a18..0748274c4 100644
---
a/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/EnhancementProject.java
+++
b/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/EnhancementProject.java
@@ -124,8 +124,6 @@ public class EnhancementProject {
ClassNode classNode = new ClassNode();
cr.accept(classNode, AsmHelper.ATTRS, 0);
ClassNodeTracker cnt = new ClassNodeTracker(this, classNode, loader);
- String name = classNode.name.replace("/", ".");
- classNodeTrackers.put(name, cnt);
return cnt;
}
diff --git
a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/TestSubclassValidator.java
b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/TestSubclassValidator.java
index 0e774c015..52890cc63 100644
---
a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/TestSubclassValidator.java
+++
b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/TestSubclassValidator.java
@@ -26,6 +26,7 @@ import org.apache.openjpa.persistence.common.apps.Department;
import org.apache.openjpa.persistence.common.apps.RuntimeTest2;
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
import org.apache.openjpa.util.asm.AsmHelper;
+import org.apache.openjpa.util.asm.EnhancementProject;
import org.apache.xbean.asm9.tree.ClassNode;
import org.junit.Test;
@@ -34,8 +35,6 @@ import jakarta.persistence.AccessType;
import jakarta.persistence.Basic;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
-import serp.bytecode.BCClass;
-import serp.bytecode.Project;
public class TestSubclassValidator extends SingleEMFTestCase {
@Override
@@ -50,7 +49,7 @@ public class TestSubclassValidator extends SingleEMFTestCase {
@Test
public void testBcSubclassValidator() throws Exception {
- Project project = new Project();
+ EnhancementProject project = new EnhancementProject();
TemporaryClassLoader tempCl = new
TemporaryClassLoader(this.getClass().getClassLoader());
final OpenJPAConfiguration conf = emf.getConfiguration();
@@ -61,7 +60,7 @@ public class TestSubclassValidator extends SingleEMFTestCase {
{
ClassNode classNode =
AsmHelper.readClassNode(EnhanceableGetterEntity.class.getClassLoader(),
EnhanceableGetterEntity.class.getName());
- final BCClass bcClass =
project.loadClass(EnhanceableGetterEntity.class.getName(), tempCl);
+ project.loadClass(EnhanceableGetterEntity.class.getName(), tempCl);
final ClassMetaData meta =
repos.getMetaData(tempCl.loadClass(EnhanceableGetterEntity.class.getName()),
tempCl, false);
PCSubclassValidator subclassValidator = new
PCSubclassValidator(meta, classNode, log, true);
subclassValidator.assertCanSubclass();
@@ -69,7 +68,7 @@ public class TestSubclassValidator extends SingleEMFTestCase {
{
ClassNode classNode =
AsmHelper.readClassNode(UnenhancedPropertyAccess.class.getClassLoader(),
UnenhancedPropertyAccess.class.getName());
- final BCClass bcClass =
project.loadClass(UnenhancedPropertyAccess.class.getName(), tempCl);
+ project.loadClass(UnenhancedPropertyAccess.class.getName(),
tempCl);
final ClassMetaData meta =
repos.getMetaData(tempCl.loadClass(UnenhancedPropertyAccess.class.getName()),
tempCl, false);
PCSubclassValidator subclassValidator = new
PCSubclassValidator(meta, classNode, log, true);
subclassValidator.assertCanSubclass();
diff --git
a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/ClassSelector.java
b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/ClassSelector.java
deleted file mode 100644
index e5c755196..000000000
---
a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/ClassSelector.java
+++ /dev/null
@@ -1,247 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.openjpa.persistence.test;
-
-import java.io.File;
-import java.io.FilenameFilter;
-import java.util.ArrayList;
-import java.util.List;
-
-import serp.bytecode.Annotations;
-import serp.bytecode.BCClass;
-import serp.bytecode.BCMethod;
-import serp.bytecode.Project;
-
-/**
- * List class names that match specific selection criteria based on
inheritance,
- * implemented interface or annotations. The classes are scanned starting from
- * a root directory or a single file. Uses serp bytecode library for reading
the
- * bytecode. The classes are not loaded in Java Virtual Machine and hence
- * dependent classes need not be in the classpath.
- *
- * @author Pinaki Poddar
- *
- */
-public class ClassSelector {
- private List<String> _supers = new ArrayList<>();
- private List<String> _interfaces = new ArrayList<>();
- private List<String> _annotations = new ArrayList<>();
-
- /**
- * Prints the class names that satisfy the following criteria
- * extends org.apache.openjpa.persistence.test.SingleEMFTestCase or
- * junit.framework.TestCase
- * and annotated with org.apache.openjpa.persistence.test.AllowFailure
- *
- * @param args the root directory of the class files to be scanned. If no
- * argument is given then assumes the current directory.
- *
- */
- public static void main(String[] args) throws Exception {
- String dir = (args.length == 0) ? System.getProperty("user.dir")
- : args[0];
- ClassSelector reader = new ClassSelector()
- .addSuper("org.apache.openjpa.persistence.test.SingleEMTestCase")
- .addSuper("org.apache.openjpa.persistence.test.SingleEMFTestCase")
- .addSuper("org.apache.openjpa.persistence.kernel.BaseKernelTest")
- .addSuper("org.apache.openjpa.persistence.query.BaseQueryTest")
-
.addSuper("org.apache.openjpa.persistence.jdbc.kernel.BaseJDBCTest")
- .addSuper(
- "org.apache.openjpa.persistence.common.utils.AbstractTestCase")
- .addAnnotation("org.apache.openjpa.persistence.test.AllowFailure");
- List<String> names = reader.list(new File(dir), true);
- String spec = reader.getSpecification();
- System.err.println("Found " + names.size() + " classes under "
- + dir + (spec.length() > 0 ? " that" : ""));
- System.err.println(spec);
- for (String name : names)
- System.err.println(name);
- }
-
- /**
- * List all the class names that match the selection.
- *
- * @param file a root file or directory
- * @param recursive if true scans all directory recursively
- * @return list of class names that match the selection.
- */
- public List<String> list(File file, boolean recursive) {
- List<String> names = new ArrayList<>();
- list(file, recursive, names);
- return names;
- }
-
- private void list(File file, boolean recursive, List<String> names) {
- if (file.isDirectory()) {
- if (recursive) {
- String[] children = file.list(new FilenameFilter() {
- @Override
- public boolean accept(File dir, String name) {
- return name.endsWith(".class");
- }
- });
- for (String name : children)
- list(new File(file, name), recursive, names);
- String[] dirs = file.list(new FilenameFilter() {
- @Override
- public boolean accept(File dir, String name) {
- return new File(dir, name).isDirectory();
- }
- });
- for (String name : dirs)
- list(new File(file, name), recursive, names);
- }
- } else if (file.getName().endsWith(".class")) {
- String cls = select(file);
- if (cls != null)
- names.add(cls);
- }
- }
-
- /**
- * Adds fully-qualified name of a super class for selection.
- */
- public ClassSelector addSuper(String s) {
- _supers.add(s);
- return this;
- }
-
- /**
- * Adds fully-qualified name of an interface for selection.
- */
- public ClassSelector addInterface(String s) {
- _interfaces.add(s);
- return this;
- }
-
- /**
- * Adds fully-qualified name of an annotation for selection.
- */
- public ClassSelector addAnnotation(String s) {
- _annotations.add(s);
- return this;
- }
-
- private String select(File file) {
- try {
- BCClass bcls = new Project().loadClass(file);
- if (applyInheritanceFilter(bcls)
- && applyInterfaceFilter(bcls)
- && applyAnnotationFilter(bcls))
- return bcls.getName();
- } catch (Exception e) {
- System.err.println("Error reading " + file.getAbsolutePath()
- + " : " + e);
- }
- return null;
- }
-
- /**
- * Affirms if super class of the given class matches any of the
- * selection filter names. If no super class name has been set for
- * selection then return true.
- *
- * @see #addSuper(String)
- */
- private boolean applyInheritanceFilter(BCClass bcls) {
- if (_supers.isEmpty())
- return true;
- String superc = bcls.getSuperclassName();
- return _supers.contains(superc);
- }
-
- /**
- * Affirms if interfaces of the given class match any of the
- * selection filter names. If no interface name has been set for
- * selection then return true.
- *
- * @see #addInterface(String)
- */
- private boolean applyInterfaceFilter(BCClass bcls) {
- if (_interfaces.isEmpty())
- return true;
- String[] ifaces = bcls.getInterfaceNames();
- if (ifaces == null || ifaces.length == 0)
- return false;
- for (String iface : ifaces)
- if (_interfaces.contains(iface))
- return true;
- return false;
- }
-
- /**
- * Affirms if annotations of the given class or its methods match any of
the
- * selection filter names. If no annotation name has been set for
- * selection then return true.
- *
- * @see #addAnnotation(String)
- */
- private boolean applyAnnotationFilter(BCClass bcls) {
- if (_annotations.isEmpty())
- return true;
- Annotations annos = bcls.getDeclaredRuntimeAnnotations(false);
- if (hasAnnotation(annos))
- return true;
- BCMethod[] methods = bcls.getDeclaredMethods();
- for (BCMethod m : methods) {
- annos = m.getDeclaredRuntimeAnnotations(false);
- if (hasAnnotation(annos))
- return true;
- }
- return false;
- }
-
- private boolean hasAnnotation(Annotations annos) {
- if (annos == null)
- return false;
- for (String anno : _annotations)
- if (annos.getAnnotation(anno) != null)
- return true;
- return false;
- }
-
- /**
- * Gets a printable description of the currently set selection criteria.
- */
- public String getSpecification() {
- StringBuilder tmp = new StringBuilder();
- String and = "";
- if (!_supers.isEmpty()) {
- tmp.append("\textends ");
- and = "and ";
- for (int i=0; i<_supers.size(); i++)
- tmp.append(_supers.get(i)).append(
- (i != _supers.size()-1 ? "\r\n\t or " : "\r\n"));
- }
- if (!_interfaces.isEmpty()) {
- tmp.append("\t" + and + "implements ");
- and = "and ";
- for (int i=0; i<_interfaces.size(); i++)
- tmp.append(_interfaces.get(i)).append(
- (i != _interfaces.size()-1 ? "\r\n\t or " :
"\r\n"));
- }
- if (!_annotations.isEmpty()) {
- tmp.append("\t" + and + "annotatated with ");
- for (int i=0; i<_annotations.size(); i++)
- tmp.append(_annotations.get(i))
- .append((i != _annotations.size()-1 ? " or " : "\r\n"));
- }
- return tmp.toString();
- }
-}