You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cl...@apache.org on 2014/05/06 16:59:52 UTC

svn commit: r1592767 - in /felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation: ClassLoaderAwareClassWriter.java Manipulator.java NoClassLoaderClassWriter.java

Author: clement
Date: Tue May  6 14:59:52 2014
New Revision: 1592767

URL: http://svn.apache.org/r1592767
Log:
To correctly compute the frames, we need a way to load classes - so a classloader. The manipulator now takes a classloader as parameter used for this purpose. (FELIX-4509).

Added:
    felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/ClassLoaderAwareClassWriter.java
      - copied, changed from r1592381, felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/NoClassLoaderClassWriter.java
Removed:
    felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/NoClassLoaderClassWriter.java
Modified:
    felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/Manipulator.java

Copied: felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/ClassLoaderAwareClassWriter.java (from r1592381, felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/NoClassLoaderClassWriter.java)
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/ClassLoaderAwareClassWriter.java?p2=felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/ClassLoaderAwareClassWriter.java&p1=felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/NoClassLoaderClassWriter.java&r1=1592381&r2=1592767&rev=1592767&view=diff
==============================================================================
--- felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/NoClassLoaderClassWriter.java (original)
+++ felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/ClassLoaderAwareClassWriter.java Tue May  6 14:59:52 2014
@@ -19,29 +19,30 @@
 
 package org.apache.felix.ipojo.manipulation;
 
-import org.objectweb.asm.ClassReader;
 import org.objectweb.asm.ClassWriter;
 
 /**
- * An extension of {@link org.objectweb.asm.ClassWriter} that doe snot trigger class loading to compute the common super
- * class. It generally returns Object.
+ * An extension of {@link org.objectweb.asm.ClassWriter} that uses a specific classloader to load classes.
  */
-public class NoClassLoaderClassWriter extends ClassWriter {
+public class ClassLoaderAwareClassWriter extends ClassWriter {
 
     private static final String OBJECT_INTERNAL_NAME = "java/lang/Object";
+    private final String className;
+    private final String superClass;
+    private final ClassLoader classLoader;
 
-    public NoClassLoaderClassWriter(ClassReader reader, int flags) {
-        super(reader, flags);
-    }
-
-    public NoClassLoaderClassWriter(int flags) {
+    public ClassLoaderAwareClassWriter(int flags, String className, String superClass, ClassLoader loader) {
         super(flags);
+        this.className = className;
+        this.superClass = superClass;
+        this.classLoader = loader;
     }
 
     /**
      * Implements the common super class lookup to be a bit more permissive. First we check is type1 == type2,
      * because in this case, the lookup is done. Then, if one of the class is Object,
      * returns object. If both checks failed, it returns Object.
+     *
      * @param type1 the first class
      * @param type2 the second class
      * @return the common super class
@@ -58,8 +59,34 @@ public class NoClassLoaderClassWriter ex
             return OBJECT_INTERNAL_NAME;
         }
 
-        // We shunt the rest of the process.
-        return OBJECT_INTERNAL_NAME;
+        // If either of these class names are the current class then we can short
+        // circuit to the superclass (which we already know)
+        if (type1.equals(className.replace(".", "/")) && superClass != null) {
+            return getCommonSuperClass(superClass.replace(".", "/"), type2);
+        } else if (type2.equals(className.replace(".", "/")) && superClass != null)
+            return getCommonSuperClass(type1, superClass.replace(".", "/"));
+
+        Class<?> c, d;
+        try {
+            c = classLoader.loadClass(type1.replace('/', '.'));
+            d = classLoader.loadClass(type2.replace('/', '.'));
+        } catch (Exception e) {
+            throw new RuntimeException(e.toString());
+        }
+        if (c.isAssignableFrom(d)) {
+            return type1;
+        }
+        if (d.isAssignableFrom(c)) {
+            return type2;
+        }
+        if (c.isInterface() || d.isInterface()) {
+            return "java/lang/Object";
+        } else {
+            do {
+                c = c.getSuperclass();
+            } while (!c.isAssignableFrom(d));
+            return c.getName().replace('.', '/');
+        }
     }
 }
 

Modified: felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/Manipulator.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/Manipulator.java?rev=1592767&r1=1592766&r2=1592767&view=diff
==============================================================================
--- felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/Manipulator.java (original)
+++ felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/Manipulator.java Tue May  6 14:59:52 2014
@@ -38,6 +38,10 @@ import java.util.*;
  */
 public class Manipulator {
     /**
+     * A classloader used to compute frames.
+     */
+    private final ClassLoader m_classLoader;
+    /**
      * Store the visited fields : [name of the field, type of the field].
      */
     private Map<String, String> m_fields;
@@ -77,6 +81,11 @@ public class Manipulator {
      */
     private String m_className;
 
+    public Manipulator(ClassLoader loader) {
+        // No classloader set, use current one.
+        m_classLoader = loader;
+    }
+
     /**
      * Checks the given bytecode, determines if the class was already manipulated, and collect the metadata about the
      * class.
@@ -119,7 +128,8 @@ public class Manipulator {
         if (!m_alreadyManipulated) {
             InputStream is2 = new ByteArrayInputStream(origin);
             ClassReader reader = new ClassReader(is2);
-            ClassWriter writer = new NoClassLoaderClassWriter(ClassWriter.COMPUTE_FRAMES);
+            ClassWriter writer = new ClassLoaderAwareClassWriter(ClassWriter.COMPUTE_FRAMES, m_className, m_superClass,
+                    m_classLoader);
             ClassManipulator process = new ClassManipulator(new CheckClassAdapter(writer, false), this);
             if (m_version >= Opcodes.V1_6) {
                 reader.accept(process, ClassReader.EXPAND_FRAMES);
@@ -262,7 +272,7 @@ public class Manipulator {
             InputStream is1 = new ByteArrayInputStream(bytecode);
 
             ClassReader cr = new ClassReader(is1);
-            ClassWriter cw = new NoClassLoaderClassWriter(ClassWriter.COMPUTE_FRAMES);
+            ClassWriter cw = new ClassLoaderAwareClassWriter(ClassWriter.COMPUTE_FRAMES, inner, null, m_classLoader);
             InnerClassAdapter adapter = new InnerClassAdapter(inner, cw, m_className, this);
             if (m_version >= Opcodes.V1_6) {
                 cr.accept(adapter, ClassReader.EXPAND_FRAMES);