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 032c6fc7fedb9ae6230a6730cdf7ffb4246119e7
Author: Mark Struberg <strub...@apache.org>
AuthorDate: Thu Jun 1 14:21:05 2023 +0200

    OPENJPA-2911 Bridge from BCClass <-> ASM ClassNode
    
    This will allow us to smoothly migrate from Serp to ASM
---
 .../org/apache/openjpa/jdbc/sql/SQLBuffer.java     | 10 +++---
 .../org/apache/openjpa/enhance/PCEnhancer.java     | 39 ++++++++++++--------
 .../openjpa/meta/InterfaceImplGenerator.java       |  2 +-
 .../org/apache/openjpa/util/asm/AsmHelper.java     | 39 ++++++++++++++++++--
 .../apache/openjpa/util/asm/ClassNodeTracker.java  | 42 ++++++++++++++++++++++
 .../enhance/TestEnhancementWithMultiplePUs.java    |  3 +-
 6 files changed, 112 insertions(+), 23 deletions(-)

diff --git 
a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLBuffer.java 
b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLBuffer.java
index ac052da20..661de54d6 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLBuffer.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLBuffer.java
@@ -142,9 +142,9 @@ public final class SQLBuffer
 
         if (!paramOnly) {
             if (sqlIndex == _sql.length())
-                _sql.append(buf._sql.toString());
+                _sql.append(buf._sql);
             else
-                _sql.insert(sqlIndex, buf._sql.toString());
+                _sql.insert(sqlIndex, buf._sql);
         }
 
         if (buf._params != null) {
@@ -326,7 +326,7 @@ public final class SQLBuffer
         if (o == null)
             _sql.append("NULL");
         else if (o instanceof Raw)
-            _sql.append(o.toString());
+            _sql.append(o);
         else {
             Class<?> type = Filters.wrap(o.getClass());
             if (useParamToken || !validParamLiteralType(type)) {
@@ -366,7 +366,7 @@ public final class SQLBuffer
 
                 } else if ( type == Character.class ) {
                     if (_dict.storeCharsAsNumbers) {
-                        _sql.append(Integer.toString((Character) o));
+                        _sql.append(o);
                     } else {
                         _sql.append("'" + o.toString().replace("'", "''") + 
"'");
                     }
@@ -375,7 +375,7 @@ public final class SQLBuffer
                     // We store B(b)ooleans as ints. Convert
                     
_sql.append(_dict.getBooleanRepresentation().getRepresentation(b));
                 } else {
-                    _sql.append(o.toString());
+                    _sql.append(o);
                 }
             }
         }
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 9a0cb32b0..aef244847 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
@@ -96,12 +96,15 @@ import org.apache.openjpa.util.ShortId;
 import org.apache.openjpa.util.StringId;
 import org.apache.openjpa.util.UserException;
 import org.apache.openjpa.util.asm.AsmHelper;
+import org.apache.openjpa.util.asm.ClassNodeTracker;
 import org.apache.openjpa.util.asm.ClassWriterTracker;
 import org.apache.xbean.asm9.Opcodes;
 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.InsnNode;
+import org.apache.xbean.asm9.tree.LdcInsnNode;
 import org.apache.xbean.asm9.tree.MethodNode;
 import org.apache.xbean.asm9.tree.VarInsnNode;
 
@@ -289,8 +292,7 @@ public class PCEnhancer {
      * @param loader the environment classloader to use for loading
      * classes and resources.
      */
-    public PCEnhancer(OpenJPAConfiguration conf, BCClass type,
-        MetaDataRepository repos, ClassLoader loader) {
+    public PCEnhancer(OpenJPAConfiguration conf, BCClass type, 
MetaDataRepository repos, ClassLoader loader) {
         _managedType = type;
         _pc = type;
 
@@ -326,8 +328,7 @@ public class PCEnhancer {
      *
      * @since 1.1.0
      */
-    public PCEnhancer(MetaDataRepository repos, BCClass type,
-        ClassMetaData meta) {
+    public PCEnhancer(MetaDataRepository repos, BCClass type, ClassMetaData 
meta) {
         _managedType = type;
         _pc = type;
 
@@ -373,14 +374,6 @@ public class PCEnhancer {
         return className;
     }
 
-    /**
-     * Constructor. Supply configuration, type, and metadata.
-     */
-    public PCEnhancer(OpenJPAConfiguration conf, BCClass type,
-        ClassMetaData meta) {
-        this(conf, type, meta.getRepository());
-    }
-
     /**
      * Return the bytecode representation of the persistence-capable class
      * being manipulated.
@@ -3076,10 +3069,17 @@ public class PCEnhancer {
      */
     private void enhanceClass() {
         // make the class implement PersistenceCapable
-        _pc.declareInterface(PCTYPE);
+        //_pc.declareInterface(PCTYPE);
+
+        final ClassNodeTracker classNodeTracker = AsmHelper.toClassNode(_pc);
+
+        // make the class implement PersistenceCapable
+        
classNodeTracker.getClassNode().interfaces.add(Type.getInternalName(PCTYPE));
 
         // add a version stamp
-        addGetEnhancementContractVersionMethod();
+        addGetEnhancementContractVersionMethod(classNodeTracker);
+
+         AsmHelper.readIntoBCClass(classNodeTracker, _pc);
 
         // find the default constructor
         BCMethod method = _pc.getDeclaredMethod("<init>", (String[]) null);
@@ -4893,6 +4893,17 @@ public class PCEnhancer {
         return setter;
     }
 
+    private void addGetEnhancementContractVersionMethod(ClassNodeTracker cnt) {
+        MethodNode methodNode = new MethodNode(Opcodes.ACC_PUBLIC,
+                                               PRE + 
"GetEnhancementContractVersion",
+                                               
Type.getMethodDescriptor(Type.INT_TYPE),
+                                               null, null);
+        methodNode.instructions.add(new LdcInsnNode(ENHANCER_VERSION));
+        methodNode.instructions.add(new InsnNode(Opcodes.IRETURN));
+        cnt.getClassNode().methods.add(methodNode);
+    }
+
+    @Deprecated //X TODO REMOVE
     private void addGetEnhancementContractVersionMethod() {
         // public int getEnhancementContractVersion()
         BCMethod method = _pc.declareMethod(PRE +
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 1ae8f1adc..474e720a3 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
@@ -124,7 +124,7 @@ class InterfaceImplGenerator {
                 iface)).setFatal(true);
         try {
             // load the Class<?> for real.
-            impl = Class.forName(bc.getName(), true, enhLoader);
+            impl = Class.forName(enhancer.getPCBytecode().getName(), true, 
enhLoader);
         } catch (Throwable t) {
             throw new InternalException(_loc.get("interface-load2", iface,
                 enhLoader), t).setFatal(true);
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 1f44aba54..5a819dc14 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
@@ -19,6 +19,7 @@ package org.apache.openjpa.util.asm;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 
 import org.apache.xbean.asm9.ClassReader;
@@ -78,7 +79,7 @@ public final class AsmHelper {
     }
 
     /**
-     * temporary helper class to convert BCClass to ASM
+     * 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) {
@@ -102,10 +103,44 @@ public final class AsmHelper {
         return bcClass;
     }
 
+    /**
+     * temporary helper class to convert BCClass to ASM ClassNode
+     * @deprecated must get removed when done with migrating from Serp to ASM
+     */
+    public static ClassNodeTracker toClassNode(BCClass bcClass) {
+        ClassReader cr = new ClassReader(bcClass.toByteArray());
+        ClassNode classNode = new ClassNode(Opcodes.ASM9);
+        cr.accept(classNode, 0);
+
+        return new ClassNodeTracker(classNode, bcClass.getClassLoader());
+    }
+
+    /**
+     * Take the changes from ClassNodeTracker and read it into the given 
BCClass instance.
+     * Effectively replace all the content of BCClass with the content from 
our ClassNode
+     */
+    public static void readIntoBCClass(ClassNodeTracker cnt, BCClass bcClass) {
+
+        // sadly package scoped
+        try {
+            Method readMethod = BCClass.class.getDeclaredMethod("read", 
InputStream.class, ClassLoader.class);
+
+            ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
+            cnt.getClassNode().accept(cw);
+            final byte[] classBytes = cw.toByteArray();
+            ByteArrayInputStream bais = new ByteArrayInputStream(classBytes);
+
+            readMethod.setAccessible(true);
+            readMethod.invoke(bcClass, bais, bcClass.getClassLoader());
+        }
+        catch (NoSuchMethodException | IllegalAccessException | 
InvocationTargetException e) {
+            throw new RuntimeException(e);
+        }
+    }
 
     /**
      * Calclates the proper Return instruction opcode for the given class
-     * 
+     *
      * @param type the type to get returned
      * @return the proper Opcode RETURN, ARETURN, IRETURN, etc
      */
diff --git 
a/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/ClassNodeTracker.java
 
b/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/ClassNodeTracker.java
new file mode 100644
index 000000000..a9e911421
--- /dev/null
+++ 
b/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/ClassNodeTracker.java
@@ -0,0 +1,42 @@
+/*
+ * 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.util.asm;
+
+import org.apache.xbean.asm9.tree.ClassNode;
+
+/**
+ * Helper class to transit from BCClass to ASM
+ *
+ * @author <a href="mailto:strub...@apache.org";>Mark Struberg</a>
+ */
+public class ClassNodeTracker {
+    private final ClassNode classNode;
+    private final ClassLoader cl;
+
+    public ClassNodeTracker(ClassNode classNode, ClassLoader cl) {
+        this.classNode = classNode;
+        this.cl = cl;
+    }
+
+    public ClassNode getClassNode() {
+        return classNode;
+    }
+
+    public ClassLoader getClassLoader() {
+        return cl;
+    }
+}
diff --git 
a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/TestEnhancementWithMultiplePUs.java
 
b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/TestEnhancementWithMultiplePUs.java
index a6c63ac33..875358865 100644
--- 
a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/TestEnhancementWithMultiplePUs.java
+++ 
b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/TestEnhancementWithMultiplePUs.java
@@ -56,7 +56,8 @@ public class TestEnhancementWithMultiplePUs
         PCEnhancer enhancer = new PCEnhancer(conf, bc, repos, loader);
 
         assertEquals(PCEnhancer.ENHANCE_PC, enhancer.run());
-        assertTrue(Arrays.asList(bc.getInterfaceNames()).contains(
+
+        
assertTrue(Arrays.asList(enhancer.getPCBytecode().getInterfaceNames()).contains(
             PersistenceCapable.class.getName()));
     }
 

Reply via email to