You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2010/12/01 15:59:17 UTC

svn commit: r1041035 - in /myfaces/core/trunk/impl/src: main/java/org/apache/myfaces/config/annotation/_ClassByteCodeAnnotationFilter.java test/java/org/apache/myfaces/config/annotation/ClassByteCodeAnnotationFilterTest.java

Author: lu4242
Date: Wed Dec  1 14:59:17 2010
New Revision: 1041035

URL: http://svn.apache.org/viewvc?rev=1041035&view=rev
Log:
MYFACES-2930 ClassByteCodeAnnotationFilter doesn't read the constants pool correctly (Thanks to Christian Kaltepoth for this patch)

Added:
    myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/config/annotation/ClassByteCodeAnnotationFilterTest.java
Modified:
    myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/annotation/_ClassByteCodeAnnotationFilter.java

Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/annotation/_ClassByteCodeAnnotationFilter.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/annotation/_ClassByteCodeAnnotationFilter.java?rev=1041035&r1=1041034&r2=1041035&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/annotation/_ClassByteCodeAnnotationFilter.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/annotation/_ClassByteCodeAnnotationFilter.java Wed Dec  1 14:59:17 2010
@@ -21,6 +21,8 @@ package org.apache.myfaces.config.annota
 import java.io.DataInput;
 import java.io.IOException;
 import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 /**
  * Scan .class files for annotation signature directly, without load them.
@@ -31,6 +33,9 @@ import java.util.Set;
  */
 class _ClassByteCodeAnnotationFilter
 {
+    
+    private static final Logger log = Logger.getLogger(_ClassByteCodeAnnotationFilter.class.getName());
+    
     //Constants used to define type in cp_info structure
     private static final int CP_INFO_CLASS = 7;
     private static final int CP_INFO_FIELD_REF = 9;
@@ -156,6 +161,8 @@ class _ClassByteCodeAnnotationFilter
                     //u4 low_bytes
                     in.readInt();
                     in.readInt();
+                    // this tag takes two entries in the constants pool
+                    i++;
                     break;
                 case CP_INFO_NAME_AND_TYPE: //ignore
                     //u2 name_index
@@ -164,9 +171,13 @@ class _ClassByteCodeAnnotationFilter
                     in.readUnsignedShort();
                     break;
                 default:
-                    //TODO: THIS SHOULD NOT HAPPEN! Log error info
+                    // THIS SHOULD NOT HAPPEN! Log error info
                     // and break for loop, because from this point
                     // we are reading corrupt data.
+                    if (log.isLoggable(Level.WARNING))
+                    {
+                        log.warning("Unknown tag in constants pool: " + tag);
+                    }
                     i = constantsPoolCount;
                     break;
             }

Added: myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/config/annotation/ClassByteCodeAnnotationFilterTest.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/config/annotation/ClassByteCodeAnnotationFilterTest.java?rev=1041035&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/config/annotation/ClassByteCodeAnnotationFilterTest.java (added)
+++ myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/config/annotation/ClassByteCodeAnnotationFilterTest.java Wed Dec  1 14:59:17 2010
@@ -0,0 +1,115 @@
+package org.apache.myfaces.config.annotation;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.faces.bean.ManagedBean;
+
+import junit.framework.TestCase;
+
+public class ClassByteCodeAnnotationFilterTest extends TestCase
+{
+
+    /**
+     * The annotation names to scan for
+     */
+    private Set<String> annotationNames = null;
+
+    /**
+     * The tested class
+     */
+    private _ClassByteCodeAnnotationFilter filter = null;
+
+    @Override
+    protected void setUp() throws Exception
+    {
+        super.setUp();
+        filter = new _ClassByteCodeAnnotationFilter();
+        annotationNames = new HashSet<String>(
+                Arrays.asList("Ljavax/faces/bean/ManagedBean;")
+        );
+    }
+
+    @Override
+    protected void tearDown() throws Exception
+    {
+        super.tearDown();
+        filter = null;
+        annotationNames = null;
+    }
+
+    /**
+     * Test that filter returns <code>false</code> for beans without annotations 
+     */
+    public void testBeanWithoutAnnotations() throws IOException
+    {
+        DataInputStream byteCode = getDataInputStreamForClass(ClassWithoutAnnotations.class);
+        assertFalse(filter.couldContainAnnotationsOnClassDef(byteCode, annotationNames));
+    }
+
+    /**
+     * Test that filter returns <code>true</code> for a bean with a {@link ManagedBean} annotation 
+     */
+    public void testBeanWithManagedBeanAnnotation() throws IOException
+    {
+        DataInputStream byteCode = getDataInputStreamForClass(ClassWithManagedBeanAnnotation.class);
+        assertTrue(filter.couldContainAnnotationsOnClassDef(byteCode, annotationNames));
+    }
+
+    /**
+     * Test that filter returns <code>false</code> for a bean with no annotations and
+     * a long constant in the constants pool. 
+     */
+    public void testBeanWithLongConstant() throws IOException
+    {
+        DataInputStream byteCode = getDataInputStreamForClass(ClassWithLongConstant.class);
+        assertFalse(filter.couldContainAnnotationsOnClassDef(byteCode, annotationNames));
+    }
+
+    /**
+     * Helper method to load a .class file from the classpath
+     * @param clazz the {@link Class} object for the class to load
+     * @return The {@link DataInputStream} of the .class file
+     */
+    private DataInputStream getDataInputStreamForClass(Class<?> clazz)
+    {
+        ClassLoader cl = Thread.currentThread().getContextClassLoader();
+        String resourceName = clazz.getName().replace('.', '/') + ".class";
+        InputStream stream = cl.getResourceAsStream(resourceName);
+        assertNotNull("Cannot find class: " + clazz.getName(), stream);
+        return new DataInputStream(stream);
+    }
+
+    /**
+     * A class without any annotations
+     */
+    public static class ClassWithoutAnnotations
+    {
+        // nothing
+    }
+
+    /**
+     * A class with a {@link ManagedBean} annotation
+     */
+    @ManagedBean
+    public static class ClassWithManagedBeanAnnotation
+    {
+
+    }
+
+    /**
+     * A class without a long constants in the constant pool
+     */
+    public static class ClassWithLongConstant
+    {
+        public final static long value1 = 9223362036854775807l;
+        public final static long value2 = 9223362036854775808l;
+        public final static long value3 = 9223362036854775809l;
+        public final static long value4 = 9223362036854775801l;
+    }
+
+}