myfaces-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bhue...@apache.org
Subject svn commit: r910077 - in /myfaces/extensions/scripting/branches/1_1/core/core/src: main/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/ main/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/adapter/ mai...
Date Sun, 14 Feb 2010 21:27:01 GMT
Author: bhuemer
Date: Sun Feb 14 21:27:00 2010
New Revision: 910077

URL: http://svn.apache.org/viewvc?rev=910077&view=rev
Log:
- ASM dependency reading reimplemented.

Added:
    myfaces/extensions/scripting/branches/1_1/core/core/src/main/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/asm/
      - copied from r910053, myfaces/extensions/scripting/branches/1_1/core/core/src/main/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/adapter/
    myfaces/extensions/scripting/branches/1_1/core/core/src/main/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/asm/AsmClassReadingDependencyScanner.java
      - copied, changed from r910053, myfaces/extensions/scripting/branches/1_1/core/core/src/main/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/ClassReadingDependencyScanner.java
    myfaces/extensions/scripting/branches/1_1/core/core/src/test/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/
    myfaces/extensions/scripting/branches/1_1/core/core/src/test/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/asm/
    myfaces/extensions/scripting/branches/1_1/core/core/src/test/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/asm/AsmClassReadingDependencyScannerTest.java
Removed:
    myfaces/extensions/scripting/branches/1_1/core/core/src/main/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/ClassReadingDependencyScanner.java
    myfaces/extensions/scripting/branches/1_1/core/core/src/main/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/adapter/
Modified:
    myfaces/extensions/scripting/branches/1_1/core/core/src/main/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/asm/ClassVisitorAdapter.java
    myfaces/extensions/scripting/branches/1_1/core/core/src/main/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/asm/MethodVisitorAdapter.java

Copied: myfaces/extensions/scripting/branches/1_1/core/core/src/main/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/asm/AsmClassReadingDependencyScanner.java
(from r910053, myfaces/extensions/scripting/branches/1_1/core/core/src/main/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/ClassReadingDependencyScanner.java)
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/branches/1_1/core/core/src/main/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/asm/AsmClassReadingDependencyScanner.java?p2=myfaces/extensions/scripting/branches/1_1/core/core/src/main/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/asm/AsmClassReadingDependencyScanner.java&p1=myfaces/extensions/scripting/branches/1_1/core/core/src/main/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/ClassReadingDependencyScanner.java&r1=910053&r2=910077&rev=910077&view=diff
==============================================================================
--- myfaces/extensions/scripting/branches/1_1/core/core/src/main/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/ClassReadingDependencyScanner.java
(original)
+++ myfaces/extensions/scripting/branches/1_1/core/core/src/main/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/asm/AsmClassReadingDependencyScanner.java
Sun Feb 14 21:27:00 2010
@@ -16,24 +16,33 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.myfaces.extensions.scripting.loader.dependencies.scanner;
+package org.apache.myfaces.extensions.scripting.loader.dependencies.scanner.asm;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.myfaces.extensions.scripting.loader.dependencies.registry.DependencyRegistry;
-import org.apache.myfaces.extensions.scripting.loader.dependencies.scanner.adapter.ClassVisitorAdapter;
+import org.apache.myfaces.extensions.scripting.loader.dependencies.scanner.DependencyScanner;
+import org.objectweb.asm.AnnotationVisitor;
 import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Type;
 
 import java.io.IOException;
 import java.io.InputStream;
 
 /**
- * 
+ * <p>A dependency scanner that uses the ASM library to read class files. In the course
of this
+ * process it determines the dependencies of a class and stores them in a given dependency
+ * registry.</p>
+ *
+ * @author Bernhard Huemer
  */
-public class ClassReadingDependencyScanner implements DependencyScanner {
+public class AsmClassReadingDependencyScanner implements DependencyScanner {
 
     /** The logger instance for this class. */
-    private static final Log logger = LogFactory.getLog(ClassReadingDependencyScanner.class);
+    private static final Log logger = LogFactory.getLog(AsmClassReadingDependencyScanner.class);
 
     // ------------------------------------------ DependencyScanner methods
 
@@ -42,29 +51,259 @@
             InputStream classStream =
                     classLoader.getResourceAsStream(className.replace('.', '/') + ".class");
             ClassReader reader = new ClassReader(classStream);
-            reader.accept(new ClassScanner(registry), 0);
+            reader.accept(new ClassScanner(registry, className), 0);
         } catch (IOException ex) {
             logger.error("An I/O error occurred while scanning the dependencies of the class
'"
                     + className + "' using the class loader '" + classLoader + "'.", ex);
         }
     }
 
+    // ------------------------------------------ Utility methods
+
+    /**
+     * <p>Utility methods that registers a dependency on the given type.</p>
+     *
+     * @param registry the registry to use for storing dependencies
+     * @param className the name of the class you're scanning for dependencies
+     * @param dependencyClass the dependency you want to register
+     * @param declaration additional information about where the dependency has been declared
+     *                      (only required for logging purposes)
+     */
+    private void registerDependency(
+            DependencyRegistry registry, String className, String dependencyClass, String
declaration) {
+        registry.registerDependency(className, dependencyClass);
+
+        if (logger.isTraceEnabled()) {
+            logger.trace("Due to '" + declaration + "' the class '" + className
+                    + "' introduces a dependency on the class '" + dependencyClass + "'.");
+        }
+    }
+
+    /**
+     * <p>Utility methods that registers a dependency on the given type if appropriate,
+     * i.e. only if it's even a class type. Otherwise the dependency will be ignored.</p>
+     * 
+     * @param registry the registry to use for storing dependencies
+     * @param className the name of the class you're scanning for dependencies
+     * @param dependency the dependency you want to register
+     * @param declaration additional information about where the dependency has been declared
+     *                      (only required for logging purposes)
+     */
+    private void registerDependency(
+            DependencyRegistry registry, String className, Type dependency, String declaration)
{
+        if (dependency.getSort() == Type.OBJECT) {
+            registry.registerDependency(className, dependency.getClassName());
+
+            if (logger.isTraceEnabled()) {
+                logger.trace("Due to '" + declaration + "' the class '" + className
+                        + "' introduces a dependency on the class '" + dependency.getClassName()
+ "'.");
+            }
+        } else {
+            if (logger.isTraceEnabled()) {
+                logger.trace("Due to '" + declaration + "' the class '" + className + "'
introduces a dependency on the type '"
+                        + dependency.getClassName() + "', but as it's not even a class, it
will be ignored.");
+            }
+        }
+    }
+
+    /**
+     * <p>Converts a given internal name of a class into the usual representation with
+     * dots in between.</p>
+     *
+     * @param internalName the internal name of a class, i.e. the one with those slashes
+     *
+     * @return the usual class name of that given class
+     */
+    private String convertInternalNameToClassName(String internalName) {
+        return internalName.replace('/', '.');
+    }
+
     // ------------------------------------------ Private classes
 
+    /**
+     * <p>This class scans the contents of a class and determines
+     * all the dependencies of that class in doing so.</p>
+     * 
+     */
     private class ClassScanner extends ClassVisitorAdapter {
 
+        /** The registry to use for storing dependencies */
         private DependencyRegistry registry;
 
+        /** The name of the class we're scanning for dependencies */
+        private String className;
+
         // -------------------------------------- Constructors
 
-        public ClassScanner(DependencyRegistry registry) {
+        public ClassScanner(DependencyRegistry registry, String className) {
             this.registry = registry;
+            this.className = className;
         }
 
         // -------------------------------------- ClassVisitor methods
 
-        
+        /**
+         * <p>Callback method that will be called once the class reader starts scanning
a new class.</p>
+         */
+        @Override
+        public void visit(int version, int access, String name, String signature,
+                            String superClassName, String[] interfaces) {
+            registerDependency(registry, className,
+                    convertInternalNameToClassName(superClassName), "'Parent class'");
+        }
+
+        /**
+         * <p>Callback method that will be called once the class reader encounters
an annotation.</p>
+         * 
+         * @param description the class descriptor of the annotation class.
+         * @param visible <code>true</code> if the annotation is visible at runtime
+         * 
+         * @return <code>null</code> as we don't need to actually "visit" the
annotation
+         */
+        @Override
+        public AnnotationVisitor visitAnnotation(String description, boolean visible) {
+            if (visible) {
+                registerDependency(registry, className, Type.getType(description), "'Class
annotation'");
+            }
+
+            // No further investigation required as we don't have to
+            // actually scan dependencies transitively. 
+            return null;
+        }
+
+        /**
+         * <p>Callback method that will be called once the class reader encounters
a field.</p>
+         *
+         * @param access the field's access flags
+         * @param name the field's name
+         * @param description the field's descriptor (see Type)
+         * @param signature the field's signature
+         * @param value the field's initial value
+         *
+         * @return <code>null</code> as we don't need to actually "visit" the
field
+         */
+        @Override
+        public FieldVisitor visitField(int access, String name, String description, String
signature, Object value) {
+            registerDependency(registry, className,
+                    Type.getType(description), "'Type of the field [" + name + "]'");
+
+            // No further investigation required.
+            return null;
+        }
+
+        /**
+         * <p>Callback method that will be called once the class reader encounters
a method.</p>
+         * 
+         * @return a method scanner that tries to scan more dependencies in the body of the
method
+         */
+        @Override
+        public MethodVisitor visitMethod(int access, String methodName, String description,
+                                            String signature, String[] exceptions) {
+            // Register all dependencies that the method signature itself introduces ..
+            registerDependency(registry, className,
+                    Type.getReturnType(description), "'Return type of the method [" + methodName
+ "]'");
+            for (Type argumentType : Type.getArgumentTypes(description)) {
+                registerDependency(registry, className,
+                        argumentType, "'Argument type of the method [" + methodName + "]'");
+            }
+
+            // .. and then continue scanning the method body.
+            return new MethodScanner(registry, className, methodName);
+        }
+    }
+
+    /**
+     * <p>This class scans the contents of a method and determines
+     * all the dependencies of that method in doing so.</p>
+     *
+     */
+    private class MethodScanner extends MethodVisitorAdapter {
+
+        /** The registry to use for storing dependencies */
+        private DependencyRegistry registry;
+
+        /** The name of the class we're scanning for dependencies */
+        private String className;
+
+        /** The name of the method we're scanning for dependencies */
+        private String methodName;
+
+        // -------------------------------------- Constructors
+
+        public MethodScanner(DependencyRegistry registry, String className, String methodName)
{
+            this.registry = registry;
+            this.className = className;
+            this.methodName = methodName;
+        }
+
+        // -------------------------------------- MethodVisitor methods
+
+        /**
+         * <p>Callback method that will be called once the class reader
+         * encounters a local variable within a method.</p>
+         *
+         */
+        @Override
+        public void visitLocalVariable(String name, String description,
+                                        String signature, Label start, Label end, int index)
{
+            registerDependency(registry, className, Type.getType(description),
+                    "'Local variable [" + name + "] in the method [" + methodName + "]");
+        }
+
+        /**
+         * <p>Callback method that will be called once the class reader encounters
+         * a method instruction, i.e. an instruction that invokes a method.</p>
+         *  
+         */
+        @Override
+        public void visitMethodInsn(int operationCode, String owner, String name, String
description) {
+            String ownerClass = convertInternalNameToClassName(owner);
+            if (!className.equals(ownerClass)) {
+                registerDependency(registry, className, ownerClass,
+                        "'Calling the method [" + name + "] within the method [" + methodName
+ "]'");
+            }
+        }
+
+        /**
+         * <p>Callback method that will be called once the class reader encounters
+         * a type instruction, i.e. either a new statement, a cast or an instanceof
+         * check.</p>
+         *
+         */
+        @Override
+        public void visitTypeInsn(int operationCode, String type) {
+            String typeInstructionClassName = convertInternalNameToClassName(type);
+            registerDependency(registry, className, typeInstructionClassName, "'Type instruction
within the method ["
+                    + methodName + "], i.e. either a cast, a new operation, or an instanceof
check'");
+        }
 
+        /**
+         * <p>Callback method that will be called on the class reader encounters
+         * a field instruction, i.e. an instruction that accesses e.g. a static
+         * field of another class.</p>
+         * 
+         */
+        @Override
+        public void visitFieldInsn(int operationCode, String owner, String name, String description)
{
+            String ownerClass = convertInternalNameToClassName(owner);
+            if (!className.equals(ownerClass)) {
+                registerDependency(registry, className, ownerClass,
+                        "'Accessing the field [" + name + "] within the method [" + methodName
+ "]'");
+            }
+        }
+
+        /**
+         * <p>Callback method that will be called once the class reader
+         * encounters a try-catch block within a method.</p>
+         * 
+         */
+        @Override
+        public void visitTryCatchBlock(Label start, Label end, Label handler, String type)
{
+            if (type != null) { // If we're not dealing with a "finally" block
+                registerDependency(registry, className,
+                        Type.getType(type), "'TryCatch block in the method [" + methodName
+ "]'");
+            }
+        }
     }
     
 }

Modified: myfaces/extensions/scripting/branches/1_1/core/core/src/main/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/asm/ClassVisitorAdapter.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/branches/1_1/core/core/src/main/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/asm/ClassVisitorAdapter.java?rev=910077&r1=910053&r2=910077&view=diff
==============================================================================
--- myfaces/extensions/scripting/branches/1_1/core/core/src/main/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/asm/ClassVisitorAdapter.java
(original)
+++ myfaces/extensions/scripting/branches/1_1/core/core/src/main/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/asm/ClassVisitorAdapter.java
Sun Feb 14 21:27:00 2010
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.myfaces.extensions.scripting.loader.dependencies.scanner.adapter;
+package org.apache.myfaces.extensions.scripting.loader.dependencies.scanner.asm;
 
 import org.objectweb.asm.AnnotationVisitor;
 import org.objectweb.asm.Attribute;
@@ -31,6 +31,11 @@
  * just a callback method, it does nothing, and if it's a method that's supposed to
  * create another visitor, it returns <code>null</code>.</p>
  *
+ * <p>Note that I know that there is a class called ClassAdapter in the ASM library,
+ * but as far as I know this class is only a proxy, i.e. it delegates to an existing
+ * implementation of the ClassVisitor interface (at least the constructor requires
+ * you to pass an instance of this interface).</p>
+ *
  * @author Bernhard Huemer
  */
 public class ClassVisitorAdapter implements ClassVisitor {
@@ -38,7 +43,7 @@
     // ------------------------------------------ ClassVisitor methods
 
     public void visit(int version, int access, String name,
-                      String signature, String supername, String[] interfaces) {
+                      String signature, String superClassName, String[] interfaces) {
         
     }
 
@@ -46,11 +51,11 @@
         
     }
 
-    public void visitOuterClass(String owner, String name, String desc) {
+    public void visitOuterClass(String owner, String name, String description) {
 
     }
 
-    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+    public AnnotationVisitor visitAnnotation(String description, boolean visible) {
         return null;
     }
 
@@ -68,7 +73,7 @@
     }
 
     public MethodVisitor visitMethod(int access, String name,
-                                      String desc, String signature, String[] exceptions)
{
+                                      String description, String signature, String[] exceptions)
{
         return null;
     }
 

Modified: myfaces/extensions/scripting/branches/1_1/core/core/src/main/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/asm/MethodVisitorAdapter.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/branches/1_1/core/core/src/main/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/asm/MethodVisitorAdapter.java?rev=910077&r1=910053&r2=910077&view=diff
==============================================================================
--- myfaces/extensions/scripting/branches/1_1/core/core/src/main/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/asm/MethodVisitorAdapter.java
(original)
+++ myfaces/extensions/scripting/branches/1_1/core/core/src/main/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/asm/MethodVisitorAdapter.java
Sun Feb 14 21:27:00 2010
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.myfaces.extensions.scripting.loader.dependencies.scanner.adapter;
+package org.apache.myfaces.extensions.scripting.loader.dependencies.scanner.asm;
 
 import org.objectweb.asm.AnnotationVisitor;
 import org.objectweb.asm.Attribute;
@@ -30,6 +30,11 @@
  * just a callback method, it does nothing, and if it's a method that's supposed to
  * create another visitor, it returns <code>null</code>.</p>
  *
+ * <p>Note that I know that there is a class called MethodAdapter in the ASM library,
+ * but as far as I know this class is only a proxy, i.e. it delegates to an existing
+ * implementation of the MethodVisitor interface (at least the constructor requires
+ * you to pass an instance of this interface).</p>
+ *
  * @author Bernhard Huemer
  */
 public class MethodVisitorAdapter implements MethodVisitor {
@@ -61,31 +66,31 @@
 
     }
 
-    public void visitInsn(int opcode) {
+    public void visitInsn(int operationCode) {
 
     }
 
-    public void visitIntInsn(int opcode, int operand) {
+    public void visitIntInsn(int operationCode, int operand) {
 
     }
 
-    public void visitVarInsn(int opcode, int var) {
+    public void visitVarInsn(int operationCode, int var) {
         
     }
 
-    public void visitTypeInsn(int opcode, String type) {
+    public void visitTypeInsn(int operationCode, String type) {
 
     }
 
-    public void visitFieldInsn(int opcode, String owner, String name, String desc) {
+    public void visitFieldInsn(int operationCode, String owner, String name, String description)
{
         
     }
 
-    public void visitMethodInsn(int opcode, String owner, String name, String desc) {
+    public void visitMethodInsn(int operationCode, String owner, String name, String description)
{
 
     }
 
-    public void visitJumpInsn(int opcode, Label label) {
+    public void visitJumpInsn(int operationCode, Label label) {
 
     }
 
@@ -109,7 +114,7 @@
 
     }
 
-    public void visitMultiANewArrayInsn(String desc, int dims) {
+    public void visitMultiANewArrayInsn(String description, int dims) {
 
     }
 
@@ -118,7 +123,7 @@
     }
 
     public void visitLocalVariable(
-            String name, String desc, String signature, Label start, Label end, int index)
{
+            String name, String description, String signature, Label start, Label end, int
index) {
 
     }
 

Added: myfaces/extensions/scripting/branches/1_1/core/core/src/test/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/asm/AsmClassReadingDependencyScannerTest.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/branches/1_1/core/core/src/test/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/asm/AsmClassReadingDependencyScannerTest.java?rev=910077&view=auto
==============================================================================
--- myfaces/extensions/scripting/branches/1_1/core/core/src/test/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/asm/AsmClassReadingDependencyScannerTest.java
(added)
+++ myfaces/extensions/scripting/branches/1_1/core/core/src/test/java/org/apache/myfaces/extensions/scripting/loader/dependencies/scanner/asm/AsmClassReadingDependencyScannerTest.java
Sun Feb 14 21:27:00 2010
@@ -0,0 +1,28 @@
+package org.apache.myfaces.extensions.scripting.loader.dependencies.scanner.asm;
+
+import junit.framework.TestCase;
+import org.apache.myfaces.extensions.scripting.loader.dependencies.registry.DefaultDependencyRegistry;
+import org.apache.myfaces.extensions.scripting.loader.dependencies.registry.DependencyRegistry;
+import org.apache.myfaces.extensions.scripting.loader.dependencies.scanner.DependencyScanner;
+
+import java.util.Set;
+
+/**
+ *
+ */
+public class AsmClassReadingDependencyScannerTest extends TestCase {
+
+    // ------------------------------------------ Test methods
+
+    public void testScanDependencies() throws Exception {
+        DependencyRegistry registry = new DefaultDependencyRegistry();
+
+        DependencyScanner scanner = new AsmClassReadingDependencyScanner();
+        scanner.scan(registry, getClass().getClassLoader(), getClass().getName());
+
+        Set<String> registryDependencies = registry.getDependentClasses(DependencyRegistry.class.getName());
+        assertTrue(registryDependencies.size() > 0);
+        assertTrue(registryDependencies.contains(getClass().getName()));
+    }
+
+}



Mime
View raw message