You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by sk...@apache.org on 2008/06/13 10:18:50 UTC

svn commit: r667414 - in /myfaces/orchestra/trunk/sandbox: pom.xml src/main/java/org/apache/myfaces/orchestra/dynaForm/metadata/impl/ejb/AsmHelper.java src/main/java/org/apache/myfaces/orchestra/dynaForm/metadata/impl/ejb/ClassHelperFactory.java

Author: skitching
Date: Fri Jun 13 01:18:50 2008
New Revision: 667414

URL: http://svn.apache.org/viewvc?rev=667414&view=rev
Log:
Support ASM 3.x releases as well as ASM 2.x

Modified:
    myfaces/orchestra/trunk/sandbox/pom.xml
    myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/dynaForm/metadata/impl/ejb/AsmHelper.java
    myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/dynaForm/metadata/impl/ejb/ClassHelperFactory.java

Modified: myfaces/orchestra/trunk/sandbox/pom.xml
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/sandbox/pom.xml?rev=667414&r1=667413&r2=667414&view=diff
==============================================================================
--- myfaces/orchestra/trunk/sandbox/pom.xml (original)
+++ myfaces/orchestra/trunk/sandbox/pom.xml Fri Jun 13 01:18:50 2008
@@ -64,9 +64,10 @@
     <dependency>
       <!-- 
       	- WARNING: asm versions are horribly non-compatible between major releases.
-      	- We might need to use maven-shade-plugin to instead import a private version
-      	- of asm into this project, so that orchestra can be used within projects
-      	- that use other versions of asm.
+        - The AsmHelper class currently uses reflection to support both ASM 2.x and 3.x.
+      	- An alternative would be to use maven-shade-plugin to instead import a private
+        - version of asm into this project, so that this lib does not conflict with the
+        - needs of apps that use it.
       	-->
       <groupId>asm</groupId>
       <artifactId>asm</artifactId>

Modified: myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/dynaForm/metadata/impl/ejb/AsmHelper.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/dynaForm/metadata/impl/ejb/AsmHelper.java?rev=667414&r1=667413&r2=667414&view=diff
==============================================================================
--- myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/dynaForm/metadata/impl/ejb/AsmHelper.java (original)
+++ myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/dynaForm/metadata/impl/ejb/AsmHelper.java Fri Jun 13 01:18:50 2008
@@ -21,6 +21,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.List;
@@ -48,6 +49,72 @@
     private static final Field[] FIELDS_TYPE = new Field[0];
     private static final Method[] METHODS_TYPE = new Method[0];
 
+    // These are initialised during class loading, and are effectively final.
+    // They cannot actually be final because the initialisation is done in
+    // a static method for tidiness, and the compiler isn't smart enough to
+    // figure out that this is equivalent to initialising them in the static
+    // block itself.
+    private static Method ACCEPT_METHOD;
+    private static Object ACCEPT_ARG;
+
+    static
+    {
+        initAsm();
+    }
+
+    /**
+     * Alas, the ASM project broke binary compatibility between the 2.x and 3.x
+     * release for no good reason. In order to be compatible with either version
+     * of ASM, we need to use reflection to invoke ClassReader.accept. 
+     * <p>
+     * In 2.x releases, we must call ClassReader.accept(classVisitor, boolean).
+     * In 3.x releases we must call ClassReader.accept(classVisitor, int).
+     * <p>
+     * In both cases, the second arg is a constant value (though of different type)
+     * so we set up ACCEPT_ARG to the appropriate value too.
+     * <p>
+     * The code below does not support ASM 1.x.
+     */
+    private static void initAsm() throws ExceptionInInitializerError
+    {
+        // signature for ASM 3.x
+        Class[] argsForm2 = new Class[] { ClassVisitor.class, Integer.TYPE };
+        try
+        {
+            Method m = ClassReader.class.getMethod("accept", argsForm2);
+            // ok, we are running with asm 3.0.x, 3.1.x or compatible
+            ACCEPT_METHOD = m;
+
+            // flags=SKIP_DEBUG|SKIP_CODE|SKIP_FRAMES 
+            ACCEPT_ARG = Integer.valueOf(1 | 2 | 4);
+            return;
+        }
+        catch (NoSuchMethodException e)
+        {
+            // ok
+        }
+
+        // signature for ASM 1.x and 2.x
+        Class[] argsForm1 = new Class[] { ClassVisitor.class, Boolean.TYPE };
+        try
+        {
+            Method m = ClassReader.class.getMethod("accept", argsForm1);
+            // ok, we are running with asm 1.x or 2.x
+            ACCEPT_METHOD = m;
+
+            // skipDebug=true
+            ACCEPT_ARG = Boolean.TRUE;
+            return;
+        }
+        catch (NoSuchMethodException e)
+        {
+            // ok
+        }
+
+        throw new ExceptionInInitializerError(
+                "AsmHelper cannot find compatible ClassReader.access method");
+    }
+
     private void applyVisitorToClass(Class clazz, ClassVisitor visitor)
     {
         // Note: Simply using the constructor ClassReader(clazz.getName())
@@ -55,17 +122,33 @@
         // from.
         String className = clazz.getName().replace('.', '/') + ".class";
         ClassReader cr = null;
-        InputStream is = null; 
+        InputStream is = null;
         try
         {
             is = this.getClass().getClassLoader().getResourceAsStream(className);
             cr = new ClassReader(is);
-            cr.accept(visitor, true);
+            
+            // Invoke ClassReader.accept(ClassVisitor, ?).
+            // See method initAsm for further details...
+            Object[] args = new Object[2];
+            args[0] = visitor;
+            args[1] = ACCEPT_ARG;
+            ACCEPT_METHOD.invoke(cr, args);
         }
         catch (IOException e)
         {
             throw new OrchestraException("Unable to read class " + className, e);
         }
+        catch(InvocationTargetException e)
+        {
+            // should never happen
+            throw new OrchestraException("Unable to read class " + className, e);
+        }
+        catch(IllegalAccessException e)
+        {
+            // should never happen
+            throw new OrchestraException("Unable to read class " + className, e);
+        }
         finally
         {
             if (is != null)
@@ -74,7 +157,7 @@
                 {
                     is.close();
                 }
-                catch(IOException e2)
+                catch (IOException e2)
                 {
                     // Not likely to occur, and nothing can be done about it.
                     log.error("Unable to close input stream", e2);
@@ -138,7 +221,7 @@
         // of any of the classes that those Method objects are on, unless weak
         // references are used. For now, keep things simple..
         Method[] methods = clazz.getDeclaredMethods();
-        for(Method m: methods)
+        for (Method m : methods)
         {
             String thisMethodDesc = org.objectweb.asm.Type.getMethodDescriptor(m);
             if (thisMethodDesc.equals(descriptor))

Modified: myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/dynaForm/metadata/impl/ejb/ClassHelperFactory.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/dynaForm/metadata/impl/ejb/ClassHelperFactory.java?rev=667414&r1=667413&r2=667414&view=diff
==============================================================================
--- myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/dynaForm/metadata/impl/ejb/ClassHelperFactory.java (original)
+++ myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/dynaForm/metadata/impl/ejb/ClassHelperFactory.java Fri Jun 13 01:18:50 2008
@@ -58,6 +58,10 @@
     		{
                 // not available
     		}
+            catch(ExceptionInInitializerError e)
+            {
+                // not available
+            }
 	    }
 
 		// last exit