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

commit 2b9b024f273d63e479a02cad751c28b8ef974ace
Author: Mark Struberg <strub...@apache.org>
AuthorDate: Mon Jul 3 11:06:17 2023 +0200

    OPENJPA-2911 addAccessors in ASM
---
 .../org/apache/openjpa/enhance/PCEnhancer.java     | 434 +++++++++++++--------
 .../org/apache/openjpa/util/asm/AsmHelper.java     |  21 +
 2 files changed, 286 insertions(+), 169 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 dd65bb5f5..a3d33795b 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
@@ -50,10 +50,12 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.Properties;
 import java.util.Set;
 import java.util.function.Predicate;
+import java.util.stream.Collectors;
 
 import org.apache.openjpa.conf.OpenJPAConfiguration;
 import org.apache.openjpa.conf.OpenJPAConfigurationImpl;
@@ -597,15 +599,12 @@ public class PCEnhancer {
             if (_meta != null) {
                 enhanceClass(pc);
                 addFields(pc);
-
-                //X For now we cannot take the new version as it uses LDC for 
classes which Serp doesn't understand.
-                //X So we can only enable it in a later step
                 addStaticInitializer(pc);
-                //X addStaticInitializer(); // removeme
-
                 addPCMethods();
+                addAccessors(pc);
+
+                AsmHelper.readIntoBCClass(pc, _pc);
 
-                addAccessors();
                 addAttachDetachCode();
                 addSerializationCode();
                 addCloningCode();
@@ -989,10 +988,7 @@ public class PCEnhancer {
     }
 
     private static MethodNode findMethodNode(ClassNode classNode, Method meth) 
{
-        final MethodNode methodNode = classNode.methods.stream()
-                .filter(mn -> mn.name.equals(meth.getName()) && 
mn.desc.equals(Type.getMethodDescriptor(meth)))
-                .findAny().get();
-        return methodNode;
+        return AsmHelper.getMethodNode(classNode, meth).get();
     }
 
 
@@ -1226,7 +1222,12 @@ public class PCEnhancer {
                                      "accessingField",
                                      Type.getMethodDescriptor(Type.VOID_TYPE, 
TYPE_OBJECT, Type.INT_TYPE)));
 
-        methodNode.instructions.insertBefore(currentInsn, insns);
+        if (methodNode.instructions.size() == 0) {
+            methodNode.instructions.add(insns);
+        }
+        else {
+            methodNode.instructions.insertBefore(currentInsn, insns);
+        }
     }
 
     @Deprecated
@@ -1273,7 +1274,7 @@ public class PCEnhancer {
         insns.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
                                      
Type.getInternalName(RedefinitionHelper.class),
                                      "settingField",
-                                     Type.getMethodDescriptor(Type.VOID_TYPE, 
TYPE_OBJECT, Type.INT_TYPE, Type.getType(type))));
+                                     Type.getMethodDescriptor(Type.VOID_TYPE, 
TYPE_OBJECT, Type.INT_TYPE, Type.getType(type), Type.getType(type))));
 
         methodNode.instructions.insert(currentInsn, insns);
         return insns.getLast();
@@ -1400,14 +1401,9 @@ public class PCEnhancer {
 
             addNewObjectIdInstanceMethod(true);
             addNewObjectIdInstanceMethod(false);
-            AsmHelper.readIntoBCClass(pc, _pc);
         }
         else if (_meta.hasPKFieldsFromAbstractClass()) {
             addGetIDOwningClass();
-            AsmHelper.readIntoBCClass(pc, _pc);
-        }
-        else {
-            AsmHelper.readIntoBCClass(pc, _pc);
         }
     }
 
@@ -4313,20 +4309,19 @@ public class PCEnhancer {
      * Adds synthetic field access methods that will replace all direct
      * field accesses.
      */
-    private void addAccessors()
-            throws NoSuchMethodException {
-        FieldMetaData[] fmds = getCreateSubclass() ? _meta.getFields()
-                : _meta.getDeclaredFields();
+    private void addAccessors(ClassNodeTracker cnt) throws 
NoSuchMethodException {
+        ClassNode classNode = cnt.getClassNode();
+        FieldMetaData[] fmds = getCreateSubclass() ? _meta.getFields() : 
_meta.getDeclaredFields();
         for (int i = 0; i < fmds.length; i++) {
             if (getCreateSubclass()) {
                 if (!getRedefine() && isPropertyAccess(fmds[i])) {
-                    addSubclassSetMethod(fmds[i]);
-                    addSubclassGetMethod(fmds[i]);
+                    addSubclassSetMethod(classNode, fmds[i]);
+                    addSubclassGetMethod(classNode, fmds[i]);
                 }
             }
             else {
-                addGetMethod(i, fmds[i]);
-                addSetMethod(i, fmds[i]);
+                addGetMethod(classNode, i, fmds[i]);
+                addSetMethod(classNode, i, fmds[i]);
             }
         }
     }
@@ -4335,37 +4330,67 @@ public class PCEnhancer {
      * Adds a non-static setter that delegates to the super methods, and
      * performs any necessary field tracking.
      */
-    @Deprecated
-    private void addSubclassSetMethod(FieldMetaData fmd)
-            throws NoSuchMethodException {
+    private void addSubclassSetMethod(ClassNode classNode, FieldMetaData fmd) 
throws NoSuchMethodException {
         Class propType = fmd.getDeclaredType();
         String setterName = getSetterName(fmd);
-        BCMethod setter = _pc.declareMethod(setterName, void.class,
-                                            new Class[]{propType});
-        setVisibilityToSuperMethod(setter);
-        Code code = setter.getCode(true);
+
+        MethodNode newMethod = new MethodNode(Opcodes.ACC_PUBLIC,
+                                                setterName,
+                                                
Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(propType)),
+                                                null, null);
+        classNode.methods.add(newMethod);
+        final InsnList instructions = newMethod.instructions;
+        int nextFreeVarPos = 2;
+
+        setVisibilityToSuperMethod(newMethod);
+
 
         // not necessary if we're already tracking access via redefinition
         if (!getRedefine()) {
             // get the orig value onto stack
-            code.aload().setThis();
-            addGetManagedValueCode(code, fmd);
-            int val = code.getNextLocalsIndex();
-            code.xstore().setLocal(val).setType(fmd.getDeclaredType());
-            addNotifyMutation(code, fmd, val, 0);
+            instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
+            addGetManagedValueCode(classNode, instructions, fmd, true);
+
+            int valVarPos = nextFreeVarPos++;
+            instructions.add(new 
VarInsnNode(AsmHelper.getStoreInsn(fmd.getDeclaredType()), valVarPos));
+            addNotifyMutation(classNode, newMethod, 
newMethod.instructions.getLast(), fmd, valVarPos, 0);
         }
 
         // ##### test case: B extends A. Methods defined in A. What
         // ##### happens?
         // super.setXXX(...)
-        code.aload().setThis();
-        code.xload().setParam(0).setType(propType);
-        code.invokespecial().setMethod(_managedType.getType(),
-                                       setterName, void.class, new 
Class[]{propType});
+        instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
+        instructions.add(new VarInsnNode(AsmHelper.getLoadInsn(propType), 1)); 
// 1st param
+        instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL,
+                                            managedType.getClassNode().name,
+                                            setterName,
+                                            
Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(propType))));
+        instructions.add(new InsnNode(Opcodes.RETURN));
+    }
 
-        code.vreturn();
-        code.calculateMaxLocals();
-        code.calculateMaxStack();
+    private boolean setVisibilityToSuperMethod(MethodNode method) {
+        ClassNode classNode = managedType.getClassNode();
+        final List<MethodNode> methods = classNode.methods.stream()
+                .filter(m -> m.name.equals(method.name) && 
Objects.equals(m.parameters, method.parameters))
+                .collect(Collectors.toList());
+        if (methods.isEmpty()) {
+            throw new UserException(_loc.get("no-accessor", 
_managedType.getName(), method.name));
+        }
+        MethodNode superMeth = methods.get(0);
+        method.access &= ~(Opcodes.ACC_PRIVATE |Opcodes.ACC_PUBLIC | 
Opcodes.ACC_PROTECTED);
+        if ((superMeth.access & Opcodes.ACC_PRIVATE) > 0) {
+            method.access |= Opcodes.ACC_PRIVATE;
+            return true;
+        }
+        if ((superMeth.access & Opcodes.ACC_PROTECTED) > 0) {
+            method.access |= Opcodes.ACC_PROTECTED;
+            return true;
+        }
+        if ((superMeth.access & Opcodes.ACC_PUBLIC) > 0) {
+            method.access |= Opcodes.ACC_PUBLIC;
+            return true;
+        }
+        return false;
     }
 
     private boolean setVisibilityToSuperMethod(BCMethod method) {
@@ -4398,29 +4423,40 @@ public class PCEnhancer {
      * Adds a non-static getter that delegates to the super methods, and
      * performs any necessary field tracking.
      */
-    @Deprecated
-    private void addSubclassGetMethod(FieldMetaData fmd) {
-        String methName = "get" + StringUtil.capitalize(fmd.getName());
-        if (_managedType.getMethods(methName, new Class[0]).length == 0)
-            methName = "is" + StringUtil.capitalize(fmd.getName());
-        BCMethod getter = _pc.declareMethod(methName, fmd.getDeclaredType(),
-                                            null);
-        setVisibilityToSuperMethod(getter);
-        getter.makePublic();
-        Code code = getter.getCode(true);
+    private void addSubclassGetMethod(ClassNode classNode, FieldMetaData fmd) {
+        String getterName = "get" + StringUtil.capitalize(fmd.getName());
+
+        final String finalGetterName = getterName;
+        final boolean hasGetter = managedType.getClassNode().methods.stream()
+                .filter(m -> m.name.equals(finalGetterName) && (m.parameters 
== null || m.parameters.isEmpty()))
+                .findAny()
+                .isPresent();
+        if (!hasGetter){
+            getterName = "is" + StringUtil.capitalize(fmd.getName());
+        }
+
+        final Class propType = fmd.getDeclaredType();
+        MethodNode getterMethod = new MethodNode(Opcodes.ACC_PUBLIC,
+                                                 getterName,
+                                                 
Type.getMethodDescriptor(Type.getType(propType)),
+                                                 null, null);
+        classNode.methods.add(getterMethod);
+        final InsnList instructions = getterMethod.instructions;
+        int nextFreeVarPos = 2;
 
         // if we're not already tracking field access via reflection, then we
         // must make the getter hook in lazy loading before accessing the super
         // method.
-        if (!getRedefine())
-            addNotifyAccess(code, fmd);
+        if (!getRedefine()) {
+            addNotifyAccess(getterMethod, getterMethod.instructions.getLast(), 
fmd);
+        }
 
-        code.aload().setThis();
-        code.invokespecial().setMethod(_managedType.getType(), methName,
-                                       fmd.getDeclaredType(), null);
-        code.xreturn().setType(fmd.getDeclaredType());
-        code.calculateMaxLocals();
-        code.calculateMaxStack();
+        instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
+        instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL,
+                                            managedType.getClassNode().name,
+                                            getterName,
+                                            
Type.getMethodDescriptor(Type.getType(propType))));
+        instructions.add(new InsnNode(AsmHelper.getReturnInsn(propType)));
     }
 
     /**
@@ -4431,53 +4467,51 @@ public class PCEnhancer {
      * @param index the relative number of the field
      * @param fmd   metadata about the field to get
      */
-    @Deprecated
-    private void addGetMethod(int index, FieldMetaData fmd)
-            throws NoSuchMethodException {
-        BCMethod method = createGetMethod(fmd);
-        Code code = method.getCode(true);
+    private void addGetMethod(ClassNode classNode, int index, FieldMetaData 
fmd) throws NoSuchMethodException {
+        MethodNode method = createGetMethod(classNode, fmd);
+        classNode.methods.add(method);
+        final InsnList instructions = method.instructions;
+        int nextFreeVarPos = 1;
 
         // if reads are not checked, just return the value
         byte fieldFlag = getFieldFlag(fmd);
-        if ((fieldFlag & PersistenceCapable.CHECK_READ) == 0
-                && (fieldFlag & PersistenceCapable.MEDIATE_READ) == 0) {
-            loadManagedInstance(code, true, fmd);
-            addGetManagedValueCode(code, fmd);
-            code.xreturn().setType(fmd.getDeclaredType());
-
-            code.calculateMaxStack();
-            code.calculateMaxLocals();
+        if ((fieldFlag & PersistenceCapable.CHECK_READ) == 0 && (fieldFlag & 
PersistenceCapable.MEDIATE_READ) == 0) {
+            instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
+            addGetManagedValueCode(classNode, instructions, fmd, true);
+            instructions.add(new 
InsnNode(AsmHelper.getReturnInsn(fmd.getDeclaredType())));
             return;
         }
 
         // if (inst.pcStateManager == null) return inst.<field>;
-        loadManagedInstance(code, true, fmd);
-        code.getfield().setField(SM, SMTYPE);
-        JumpInstruction ifins = code.ifnonnull();
-        loadManagedInstance(code, true, fmd);
-        addGetManagedValueCode(code, fmd);
-        code.xreturn().setType(fmd.getDeclaredType());
+        instructions.add(loadManagedInstance(true, fmd));
+        instructions.add(new FieldInsnNode(Opcodes.GETFIELD, classNode.name, 
SM, Type.getDescriptor(SMTYPE)));
+        LabelNode afterIfNonNull = new LabelNode();
+        instructions.add(new JumpInsnNode(Opcodes.IFNONNULL, afterIfNonNull));
+        instructions.add(loadManagedInstance(true, fmd));
+        addGetManagedValueCode(classNode, instructions, fmd, true);
+        instructions.add(new 
InsnNode(AsmHelper.getReturnInsn(fmd.getDeclaredType())));
 
+        instructions.add(afterIfNonNull);
         // int field = pcInheritedFieldCount + <fieldindex>;
-        int fieldLocal = code.getNextLocalsIndex();
-        ifins.setTarget(code.getstatic().setField(INHERIT, int.class));
-        code.constant().setValue(index);
-        code.iadd();
-        code.istore().setLocal(fieldLocal);
+        int fieldLocalVarPos = nextFreeVarPos++;
+        instructions.add(new FieldInsnNode(Opcodes.GETSTATIC, classNode.name, 
INHERIT, Type.INT_TYPE.getDescriptor()));
+        instructions.add(AsmHelper.getLoadConstantInsn(index));
+        instructions.add(new InsnNode(Opcodes.IADD));
+        instructions.add(new VarInsnNode(Opcodes.ISTORE, fieldLocalVarPos));
 
         // inst.pcStateManager.accessingField (field);
         // return inst.<field>;
-        loadManagedInstance(code, true, fmd);
-        code.getfield().setField(SM, SMTYPE);
-        code.iload().setLocal(fieldLocal);
-        code.invokeinterface().setMethod(SMTYPE, "accessingField", void.class,
-                                         new Class[]{int.class});
-        loadManagedInstance(code, true, fmd);
-        addGetManagedValueCode(code, fmd);
-        code.xreturn().setType(fmd.getDeclaredType());
+        instructions.add(loadManagedInstance(true, fmd));
+        instructions.add(new FieldInsnNode(Opcodes.GETFIELD, classNode.name, 
SM, Type.getDescriptor(SMTYPE)));
+        instructions.add(new VarInsnNode(Opcodes.ILOAD, fieldLocalVarPos));
+        instructions.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE,
+                                            Type.getInternalName(SMTYPE),
+                                            "accessingField",
+                                            
Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE)));
 
-        code.calculateMaxStack();
-        code.calculateMaxLocals();
+        instructions.add(loadManagedInstance(true, fmd));
+        addGetManagedValueCode(classNode, instructions, fmd, true);
+        instructions.add(new 
InsnNode(AsmHelper.getReturnInsn(fmd.getDeclaredType())));
     }
 
     /**
@@ -4488,49 +4522,59 @@ public class PCEnhancer {
      * @param index the relative number of the field
      * @param fmd   metadata about the field to set
      */
-    @Deprecated
-    private void addSetMethod(int index, FieldMetaData fmd)
-            throws NoSuchMethodException {
-        BCMethod method = createSetMethod(fmd);
-        Code code = method.getCode(true);
+    private void addSetMethod(ClassNode classNode, int index, FieldMetaData 
fmd) throws NoSuchMethodException {
+        MethodNode method = createSetMethod(classNode, fmd);
+        classNode.methods.add(method);
+        final InsnList instructions = method.instructions;
 
         // PCEnhancer uses static methods; PCSubclasser does not.
-        int firstParamOffset = getAccessorParameterOffset(fmd);
+        // for a static method there is no 'this', so index starts with zero
+        // but in that case we have the additional entity parameter on that 
position!
+        int fieldParamPos = 1;
 
         // if (inst.pcStateManager == null) inst.<field> = value;
-        loadManagedInstance(code, true, fmd);
-        code.getfield().setField(SM, SMTYPE);
-        JumpInstruction ifins = code.ifnonnull();
-        loadManagedInstance(code, true, fmd);
-        code.xload().setParam(firstParamOffset);
-        addSetManagedValueCode(code, fmd);
+        instructions.add(loadManagedInstance(true, fmd));
+        instructions.add(new FieldInsnNode(Opcodes.GETFIELD, classNode.name, 
SM, Type.getDescriptor(SMTYPE)));
+
+        LabelNode lblAfterIfNonNull = new LabelNode();
+        instructions.add(new JumpInsnNode(Opcodes.IFNONNULL, 
lblAfterIfNonNull));
+        instructions.add(loadManagedInstance(true, fmd));
+        instructions.add(new 
VarInsnNode(AsmHelper.getLoadInsn(fmd.getDeclaredType()), fieldParamPos));
+        addSetManagedValueCode(classNode, instructions, fmd);
         if (fmd.isVersion() && _addVersionInitFlag) {
             // if we are setting the version, flip the versionInit flag to true
-            loadManagedInstance(code, true);
-            code.constant().setValue(1);
+
+            instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
+            instructions.add(AsmHelper.getLoadConstantInsn(1));
+
             // pcVersionInit = true;
-            putfield(code, null, VERSION_INIT_STR, boolean.class);
+            instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, 
classNode.name, VERSION_INIT_STR, Type.BOOLEAN_TYPE.getDescriptor()));
         }
-        code.vreturn();
+        instructions.add(new InsnNode(Opcodes.RETURN));
+
+        instructions.add(lblAfterIfNonNull);
 
         // inst.pcStateManager.setting<fieldType>Field (inst,
         //     pcInheritedFieldCount + <index>, inst.<field>, value, 0);
-        ifins.setTarget(loadManagedInstance(code, true, fmd));
-        code.getfield().setField(SM, SMTYPE);
-        loadManagedInstance(code, true, fmd);
-        code.getstatic().setField(INHERIT, int.class);
-        code.constant().setValue(index);
-        code.iadd();
-        loadManagedInstance(code, true, fmd);
-        addGetManagedValueCode(code, fmd);
-        code.xload().setParam(firstParamOffset);
-        code.constant().setValue(0);
-        code.invokeinterface().setMethod(getStateManagerMethod
-                                                 (fmd.getDeclaredType(), 
"setting", false, true));
-        code.vreturn();
+        instructions.add(loadManagedInstance(true, fmd));
+        instructions.add(new FieldInsnNode(Opcodes.GETFIELD, classNode.name, 
SM, Type.getDescriptor(SMTYPE)));
 
-        code.calculateMaxStack();
-        code.calculateMaxLocals();
+        instructions.add(loadManagedInstance(true, fmd));
+        instructions.add(new FieldInsnNode(Opcodes.GETSTATIC, classNode.name, 
INHERIT, Type.INT_TYPE.getDescriptor()));
+        instructions.add(AsmHelper.getLoadConstantInsn(index));
+        instructions.add(new InsnNode(Opcodes.IADD));
+
+        instructions.add(loadManagedInstance(true, fmd));
+        addGetManagedValueCode(classNode, instructions, fmd, true);
+        instructions.add(new 
VarInsnNode(AsmHelper.getLoadInsn(fmd.getDeclaredType()), fieldParamPos));
+        instructions.add(new InsnNode(Opcodes.ICONST_0));
+
+        final Method stateMgrMethod = 
getStateManagerMethod(fmd.getDeclaredType(), "setting", false, true);
+        instructions.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE,
+                                            
Type.getInternalName(stateMgrMethod.getDeclaringClass()),
+                                            stateMgrMethod.getName(),
+                                            
Type.getMethodDescriptor(stateMgrMethod)));
+        instructions.add(new InsnNode(Opcodes.RETURN));
     }
 
     /**
@@ -5493,13 +5537,28 @@ public class PCEnhancer {
      * @return the first instruction added to <code>code</code>.
      */
     @Deprecated
-    private Instruction loadManagedInstance(Code code, boolean forStatic,
-            FieldMetaData fmd) {
+    private Instruction loadManagedInstance(Code code, boolean forStatic, 
FieldMetaData fmd) {
         if (forStatic && isFieldAccess(fmd))
             return code.aload().setParam(0);
         return code.aload().setThis();
     }
 
+    /**
+     * Add the {@link Instruction}s to load the instance to modify onto the
+     * stack, and return it. If <code>forStatic</code> is set, then
+     * <code>code</code> is in an accessor method or another static method;
+     * otherwise, it is in one of the PC-specified methods.
+     *
+     * @return the first instruction added to <code>code</code>.
+     */
+    private AbstractInsnNode loadManagedInstance(boolean forStatic, 
FieldMetaData fmd) {
+        if (forStatic && isFieldAccess(fmd)) {
+            // 1st method parameter is position 0 on the stack for a STATIC 
method!
+            return new VarInsnNode(Opcodes.ALOAD, 0);
+        }
+        return new VarInsnNode(Opcodes.ALOAD, 0); // this
+    }
+
     /**
      * Add the {@link Instruction}s to load the instance to modify onto the
      * stack, and return it.  This method should not be used to load static
@@ -5542,65 +5601,102 @@ public class PCEnhancer {
      * Create the generated getter {@link BCMethod} for <code>fmd</code>. The
      * calling environment will then populate this method's code block.
      */
-    @Deprecated
-    private BCMethod createGetMethod(FieldMetaData fmd) {
-        BCMethod getter;
+    private MethodNode createGetMethod(ClassNode classNode, FieldMetaData fmd) 
{
         if (isFieldAccess(fmd)) {
             // static <fieldtype> pcGet<field> (XXX inst)
-            BCField field = _pc.getDeclaredField(fmd.getName());
-            getter = _pc.declareMethod(PRE + "Get" + fmd.getName(), fmd.
-                getDeclaredType().getName(), new String[]{ _pc.getName() });
-            getter.setAccessFlags(field.getAccessFlags()
-                & ~Constants.ACCESS_TRANSIENT & ~Constants.ACCESS_VOLATILE);
-            getter.setStatic(true);
-            getter.setFinal(true);
+            final FieldNode field = classNode.fields.stream()
+                    .filter(f -> f.name.equals(fmd.getName()))
+                    .findFirst()
+                    .get();
+
+            MethodNode getter = new MethodNode((field.access & 
~Constants.ACCESS_TRANSIENT & ~Constants.ACCESS_VOLATILE)
+                                                          | Opcodes.ACC_FINAL 
| Opcodes.ACC_STATIC,
+                                                  PRE + "Get" + fmd.getName(),
+                                                  
Type.getMethodDescriptor(Type.getType(fmd.getDeclaredType()), 
Type.getObjectType(classNode.name)),
+                                                  null, null);
             return getter;
         }
 
         // property access:
-        // copy the user's getter method to a new name; we can't just reset
-        // the name, because that will also reset all calls to the method
+        // change the user's getter method to a new name and create a new 
method with the old name
         Method meth = (Method) fmd.getBackingMember();
-        getter = _pc.getDeclaredMethod(meth.getName(),
-            meth.getParameterTypes());
-        BCMethod newgetter = _pc.declareMethod(PRE + meth.getName(),
-            meth.getReturnType(), meth.getParameterTypes());
-        newgetter.setAccessFlags(getter.getAccessFlags());
-        newgetter.makeProtected();
-        transferCodeAttributes(getter, newgetter);
-        return getter;
+
+        MethodNode getter = AsmHelper.getMethodNode(classNode, meth).get();
+
+        // and a new method which replaces the old one
+        MethodNode newGetter =  new MethodNode(getter.access,
+                                            meth.getName(),
+                                            Type.getMethodDescriptor(meth),
+                                            null, null);
+
+        getter.name = PRE + meth.getName();
+        getter.access = (getter.access & ~Opcodes.ACC_PUBLIC & 
~Opcodes.ACC_PRIVATE) | Opcodes.ACC_PROTECTED;
+
+        moveAnnotations(getter, newGetter);
+
+        // copy over all ParemeterizedType info if any.
+        newGetter.signature = getter.signature;
+
+        return newGetter;
+    }
+
+
+    /**
+     * move the annotations over from the original method to the other method
+     */
+    private void moveAnnotations(MethodNode from, MethodNode to) {
+        if (from.visibleAnnotations != null) {
+            if (to.visibleAnnotations == null) {
+                to.visibleAnnotations = new ArrayList<>();
+            }
+            to.visibleAnnotations.addAll(from.visibleAnnotations);
+
+            from.visibleAnnotations.clear();
+        }
     }
 
     /**
      * Create the generated setter {@link BCMethod} for <code>fmd</code>. The
      * calling environment will then populate this method's code block.
      */
-    @Deprecated
-    private BCMethod createSetMethod(FieldMetaData fmd) {
-        BCMethod setter;
+    private MethodNode createSetMethod(ClassNode classNode, FieldMetaData fmd) 
{
         if (isFieldAccess(fmd)) {
             // static void pcSet<field> (XXX inst, <fieldtype> value)
-            BCField field = _pc.getDeclaredField(fmd.getName());
-            setter = _pc.declareMethod(PRE + "Set" + fmd.getName(), void.class,
-                new Class[]{ getType(_meta), fmd.getDeclaredType() });
-            setter.setAccessFlags(field.getAccessFlags()
-                & ~Constants.ACCESS_TRANSIENT & ~Constants.ACCESS_VOLATILE);
-            setter.setStatic(true);
-            setter.setFinal(true);
+            final FieldNode field = classNode.fields.stream()
+                    .filter(f -> f.name.equals(fmd.getName()))
+                    .findFirst()
+                    .get();
+            MethodNode setter = new MethodNode((field.access & 
~Constants.ACCESS_TRANSIENT & ~Constants.ACCESS_VOLATILE)
+                                                       | Opcodes.ACC_FINAL | 
Opcodes.ACC_STATIC,
+                                               PRE + "Set" + fmd.getName(),
+                                               
Type.getMethodDescriptor(Type.VOID_TYPE,
+                                                                        
Type.getType(getType(_meta)),
+                                                                        
Type.getType(fmd.getDeclaredType())),
+                                               null, null);
+
             return setter;
         }
 
         // property access:
-        // copy the user's getter method to a new name; we can't just reset
-        // the name, because that will also reset all calls to the method
-        setter = _pc.getDeclaredMethod(getSetterName(fmd),
-            new Class[]{ fmd.getDeclaredType() });
-        BCMethod newsetter = _pc.declareMethod(PRE + setter.getName(),
-            setter.getReturnName(), setter.getParamNames());
-        newsetter.setAccessFlags(setter.getAccessFlags());
-        newsetter.makeProtected();
-        transferCodeAttributes(setter, newsetter);
-        return setter;
+        // change the user's setter method to a new name and create a new 
method with the old name
+        final MethodNode setter = AsmHelper.getMethodNode(classNode, 
getSetterName(fmd), void.class, fmd.getDeclaredType()).get();
+
+        final String setterName = setter.name;
+
+        // and a new method which replaces the old one
+        MethodNode newSetter =  new MethodNode(setter.access,
+                                               setterName,
+                                               setter.desc,
+                                               null, null);
+
+        setter.name = PRE + setterName;
+        setter.access = (setter.access & ~Opcodes.ACC_PRIVATE & 
~Opcodes.ACC_PUBLIC) | Opcodes.ACC_PROTECTED;
+        moveAnnotations(setter, newSetter);
+
+        // copy over all ParemeterizedType info if any.
+        newSetter.signature = setter.signature;
+
+        return newSetter;
     }
 
     private void addGetEnhancementContractVersionMethod(ClassNodeTracker cnt) {
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 8f64b039e..ca086bb65 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
@@ -22,6 +22,8 @@ import java.io.InputStream;
 import java.lang.reflect.Array;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Optional;
 
 import org.apache.xbean.asm9.ClassReader;
 import org.apache.xbean.asm9.ClassWriter;
@@ -33,6 +35,7 @@ import org.apache.xbean.asm9.tree.FieldInsnNode;
 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.MethodNode;
 import org.apache.xbean.asm9.tree.VarInsnNode;
 
 import serp.bytecode.BCClass;
@@ -152,6 +155,24 @@ public final class AsmHelper {
         }
     }
 
+    public static Optional<MethodNode> getMethodNode(ClassNode classNode, 
Method meth) {
+        final String mDesc = Type.getMethodDescriptor(meth);
+        return classNode.methods.stream()
+                .filter(mn -> mn.name.equals(meth.getName()) && 
mn.desc.equals(mDesc))
+                .findAny();
+    }
+
+    public static Optional<MethodNode> getMethodNode(ClassNode classNode, 
String methodName, Class<?> returnType, Class<?>... paramTypes) {
+        Type[] parms = Arrays.stream(paramTypes)
+                .map(c -> Type.getType(c))
+                .toArray(Type[]::new);
+
+        final String mDesc = 
Type.getMethodDescriptor(Type.getType(returnType), parms);
+        return classNode.methods.stream()
+                .filter(mn -> mn.name.equals(methodName) && 
mn.desc.equals(mDesc))
+                .findAny();
+    }
+
     /**
      * Calclates the proper Return instruction opcode for the given class
      *

Reply via email to