You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by st...@apache.org on 2023/05/06 07:18:37 UTC

[openjpa] 12/17: OPENJPA-2909 more proxy generator fixes

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 ec946b6789184a3be7ffe7d18f59bcac4238e08e
Author: Mark Struberg <st...@apache.org>
AuthorDate: Thu May 4 12:13:08 2023 +0200

    OPENJPA-2909 more proxy generator fixes
---
 .../org/apache/openjpa/util/ProxyManagerImpl.java  | 153 ++++++++++++++++++++-
 1 file changed, 152 insertions(+), 1 deletion(-)

diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyManagerImpl.java b/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyManagerImpl.java
index 32d541d68..1c4e4e498 100644
--- a/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyManagerImpl.java
+++ b/openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyManagerImpl.java
@@ -747,7 +747,7 @@ public class ProxyManagerImpl
         delegateConstructors(ct, type, superClassFileNname);
         addInstanceVariables(ct);
         addProxyMethods(ct, false, proxyClassDef, type);
-        addProxyCollectionMethods(ct, proxyClassDef, type);
+        addProxyMapMethods(ct, proxyClassDef, type);
         proxyRecognizedMethods(ct, proxyClassDef, type, ProxyMaps.class, ProxyMap.class);
         proxySetters(ct, proxyClassDef, type);
         addWriteReplaceMethod(ct, proxyClassDef, runtime);
@@ -1028,6 +1028,157 @@ public class ProxyManagerImpl
         }
     }
 
+
+    private void addProxyMapMethods(ClassWriterTracker ct, String proxyClassDef, Class type) {
+        // change tracker
+        {
+            ct.getCw().visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_TRANSIENT,
+                    "changeTracker", Type.getDescriptor(MapChangeTracker.class), null, null).visitEnd();
+            MethodVisitor mv = ct.visitMethod(Modifier.PUBLIC, "getChangeTracker",
+                    Type.getMethodDescriptor(Type.getType(ChangeTracker.class))
+                    , null, null);
+            mv.visitCode();
+            mv.visitVarInsn(Opcodes.ALOAD, 0);
+            mv.visitFieldInsn(Opcodes.GETFIELD, proxyClassDef, "changeTracker", Type.getDescriptor(MapChangeTracker.class));
+
+            mv.visitInsn(Opcodes.ARETURN);
+            mv.visitMaxs(-1, -1);
+            mv.visitEnd();
+        }
+
+        // Map copy
+        {
+            Constructor cons = findCopyConstructor(type);
+            if (cons == null && SortedMap.class.isAssignableFrom(type)) {
+                cons = findComparatorConstructor(type);
+            }
+            Class[] params = (cons == null) ? new Class[0]
+                    : cons.getParameterTypes();
+
+            MethodVisitor mv = ct.visitMethod(Modifier.PUBLIC, "copy",
+                    Type.getMethodDescriptor(TYPE_OBJECT, TYPE_OBJECT)
+                    , null, null);
+            mv.visitCode();
+            mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(type));
+            mv.visitInsn(Opcodes.DUP);
+
+            if (params.length == 1) {
+                mv.visitVarInsn(Opcodes.ALOAD, 1);
+                if (params[0] == Comparator.class) {
+                    mv.visitTypeInsn(Opcodes.CHECKCAST, Type.getInternalName(SortedMap.class));
+                    mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, Type.getInternalName(SortedMap.class), "comparator",
+                            Type.getMethodDescriptor(Type.getType(Comparator.class)), true);
+                }
+                else {
+                    // otherwise just pass the parameter
+                    mv.visitTypeInsn(Opcodes.CHECKCAST, Type.getInternalName(params[0]));
+                }
+            }
+            mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(type), "<init>",
+                    Type.getMethodDescriptor(Type.VOID_TYPE, AsmHelper.getParamTypes(params)), false);
+
+            if (params.length == 0 || params[0] == Comparator.class) {
+                mv.visitInsn(Opcodes.DUP);
+                mv.visitVarInsn(Opcodes.ALOAD, 1);
+                mv.visitTypeInsn(Opcodes.CHECKCAST, Type.getInternalName(Collection.class));
+                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(type), "putAll",
+                        Type.getMethodDescriptor(Type.BOOLEAN_TYPE, Type.getType(Map.class)), false);
+                mv.visitInsn(Opcodes.POP);
+            }
+
+            mv.visitInsn(Opcodes.ARETURN);
+            mv.visitMaxs(-1, -1);
+            mv.visitEnd();
+        }
+
+        // key type
+        {
+            ct.getCw().visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_TRANSIENT,
+                    "keyType", Type.getDescriptor(Class.class), null, null).visitEnd();
+
+            MethodVisitor mv = ct.visitMethod(Modifier.PUBLIC, "getKeyType",
+                    Type.getMethodDescriptor(Type.getType(Class.class))
+                    , null, null);
+            mv.visitCode();
+            mv.visitVarInsn(Opcodes.ALOAD, 0);
+            mv.visitFieldInsn(Opcodes.GETFIELD, proxyClassDef, "keyType", Type.getDescriptor(Class.class));
+
+            mv.visitInsn(Opcodes.ARETURN);
+            mv.visitMaxs(-1, -1);
+            mv.visitEnd();
+        }
+
+        // value type
+        {
+            ct.getCw().visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_TRANSIENT,
+                    "valueType", Type.getDescriptor(Class.class), null, null).visitEnd();
+
+            MethodVisitor mv = ct.visitMethod(Modifier.PUBLIC, "getValueType",
+                    Type.getMethodDescriptor(Type.getType(Class.class))
+                    , null, null);
+            mv.visitCode();
+            mv.visitVarInsn(Opcodes.ALOAD, 0);
+            mv.visitFieldInsn(Opcodes.GETFIELD, proxyClassDef, "valueType", Type.getDescriptor(Class.class));
+
+            mv.visitInsn(Opcodes.ARETURN);
+            mv.visitMaxs(-1, -1);
+            mv.visitEnd();
+        }
+
+        // new instance factory
+        {
+            MethodVisitor mv = ct.visitMethod(Modifier.PUBLIC, "newInstance",
+                    Type.getMethodDescriptor(Type.getType(ProxyMap.class),
+                            Type.getType(Class.class), Type.getType(Class.class), Type.getType(Comparator.class),
+                            Type.BOOLEAN_TYPE, Type.BOOLEAN_TYPE)
+                    , null, null);
+            mv.visitCode();
+            mv.visitTypeInsn(Opcodes.NEW, proxyClassDef);
+            mv.visitInsn(Opcodes.DUP);
+
+            Constructor cons = findComparatorConstructor(type);
+            Class[] params = (cons == null) ? new Class[0] : cons.getParameterTypes();
+            if (params.length == 1) {
+                mv.visitVarInsn(Opcodes.ALOAD, 3);
+            }
+
+            mv.visitMethodInsn(Opcodes.INVOKESPECIAL, proxyClassDef, "<init>",
+                    Type.getMethodDescriptor(Type.VOID_TYPE, AsmHelper.getParamTypes(params)), false);
+
+            mv.visitVarInsn(Opcodes.ASTORE, 6);
+            mv.visitVarInsn(Opcodes.ALOAD, 6);
+            mv.visitVarInsn(Opcodes.ALOAD, 1);
+            mv.visitFieldInsn(Opcodes.PUTFIELD, proxyClassDef, "keyType", Type.getDescriptor(Class.class));
+
+            mv.visitVarInsn(Opcodes.ALOAD, 6);
+            mv.visitVarInsn(Opcodes.ALOAD, 2);
+            mv.visitFieldInsn(Opcodes.PUTFIELD, proxyClassDef, "valueType", Type.getDescriptor(Class.class));
+
+            mv.visitVarInsn(Opcodes.ILOAD, 4);
+            Label lNotTrack = new Label();
+            mv.visitJumpInsn(Opcodes.IFEQ, lNotTrack);
+            mv.visitVarInsn(Opcodes.ALOAD, 6);
+            mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(MapChangeTrackerImpl.class));
+
+            mv.visitInsn(Opcodes.DUP);
+            mv.visitVarInsn(Opcodes.ALOAD, 6);
+
+            mv.visitVarInsn(Opcodes.ILOAD, 5);
+            mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(MapChangeTrackerImpl.class), "<init>",
+                    Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(Map.class), Type.BOOLEAN_TYPE),
+                    false);
+            mv.visitFieldInsn(Opcodes.PUTFIELD, proxyClassDef, "changeTracker", Type.getDescriptor(MapChangeTracker.class));
+
+            mv.visitLabel(lNotTrack);
+            mv.visitVarInsn(Opcodes.ALOAD, 6);
+
+            mv.visitInsn(Opcodes.ARETURN);
+            mv.visitMaxs(-1, -1);
+            mv.visitEnd();
+        }
+    }
+
+
     private void proxyRecognizedMethods(ClassWriterTracker ct, String proxyClassDef, Class<?> type,
                                         Class<?> helper, Class<?> proxyType) {
         Method[] meths = type.getMethods();