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 2012/06/27 19:20:18 UTC

svn commit: r1354636 - in /felix/trunk/ipojo/manipulator/manipulator: ./ src/main/java/org/apache/felix/ipojo/manipulation/

Author: clement
Date: Wed Jun 27 17:20:17 2012
New Revision: 1354636

URL: http://svn.apache.org/viewvc?rev=1354636&view=rev
Log:
Fixed FELIX-3574

Applying the patch from Francois Valdy. Added some comments.

Modified:
    felix/trunk/ipojo/manipulator/manipulator/pom.xml
    felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/ClassChecker.java
    felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/MethodCreator.java
    felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/MethodDescriptor.java

Modified: felix/trunk/ipojo/manipulator/manipulator/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/manipulator/pom.xml?rev=1354636&r1=1354635&r2=1354636&view=diff
==============================================================================
--- felix/trunk/ipojo/manipulator/manipulator/pom.xml (original)
+++ felix/trunk/ipojo/manipulator/manipulator/pom.xml Wed Jun 27 17:20:17 2012
@@ -38,12 +38,6 @@
             <groupId>asm</groupId>
             <artifactId>asm-all</artifactId>
             <version>3.3.1</version>
-            <exclusions>
-                <exclusion>
-                    <groupId>asm</groupId>
-                    <artifactId>asm-tree</artifactId>
-                </exclusion>
-            </exclusions>
         </dependency>
         <dependency>
             <groupId>org.apache.felix</groupId>
@@ -86,7 +80,7 @@
                         <Private-Package>org.apache.felix.ipojo.manipulation,
                             org.apache.felix.ipojo.manipulation.annotations,
                             org.apache.felix.ipojo.xml.parser, org.objectweb.asm,
-                            org.objectweb.asm.commons
+                            org.objectweb.asm.commons, org.objectweb.asm.tree
                         </Private-Package>
                         <Include-Resource>
                             META-INF/LICENSE=LICENSE,
@@ -95,7 +89,7 @@
                             META-INF/DEPENDENCIES=DEPENDENCIES,
                             {maven-resources}
                         </Include-Resource>
-                        <Import-Package>!org.objectweb.asm.tree, *</Import-Package>
+                        <Import-Package>*</Import-Package>
                     </instructions>
                     <obrRepository>NONE</obrRepository>
                 </configuration>

Modified: felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/ClassChecker.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/ClassChecker.java?rev=1354636&r1=1354635&r2=1354636&view=diff
==============================================================================
--- felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/ClassChecker.java (original)
+++ felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/ClassChecker.java Wed Jun 27 17:20:17 2012
@@ -22,10 +22,10 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.TreeMap;
-
 import org.objectweb.asm.AnnotationVisitor;
 import org.objectweb.asm.ClassVisitor;
 import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.Label;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 import org.objectweb.asm.Type;
@@ -215,20 +215,16 @@ public class ClassChecker extends EmptyV
 
             if (name.equals("<init>")) {
                 if (!isGeneratedConstructor(name, desc)) {
-                    final MethodDescriptor md = new MethodDescriptor("$init", desc);
+                    final MethodDescriptor md = new MethodDescriptor("$init", desc, (access & ACC_STATIC) == ACC_STATIC);
                     m_methods.add(md);
-                    if (m_supportAnnotation) {
-                        return new AnnotationCollector(md);
-                    }
+                    return new MethodInfoCollector(md);
                 }
             } else {
                 // no constructors.
                 if (!isGeneratedMethod(name, desc)) {
-                    final MethodDescriptor md = new MethodDescriptor(name, desc);
+                    final MethodDescriptor md = new MethodDescriptor(name, desc, (access & ACC_STATIC) == ACC_STATIC);
                     m_methods.add(md);
-                    if (m_supportAnnotation) {
-                        return new AnnotationCollector(md);
-                    }
+                    return new MethodInfoCollector(md);
                 }
             }
 
@@ -323,9 +319,10 @@ public class ClassChecker extends EmptyV
      * This class collects annotations in a method.
      * This class creates an {@link AnnotationDescriptor}
      * if an annotation is found during the visit.
+     * It also collects local variables definition.
      *  @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
      */
-    private final class AnnotationCollector extends EmptyVisitor {
+    private final class MethodInfoCollector extends EmptyVisitor {
         /**
          * The method descriptor of the visited method.
          */
@@ -335,7 +332,7 @@ public class ClassChecker extends EmptyV
          * Creates an annotation collector.
          * @param md the method descriptor of the visited method.
          */
-        private AnnotationCollector(MethodDescriptor md) {
+        private MethodInfoCollector(MethodDescriptor md) {
             m_method = md;
         }
 
@@ -359,6 +356,14 @@ public class ClassChecker extends EmptyV
             }
             return null;
         }
+        
+        public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
+            m_method.addLocalVariable(name, desc, signature, index);
+        }
+        
+        public void visitEnd() {
+            m_method.end();
+        }
 
         public AnnotationVisitor visitParameterAnnotation(int id,
                 String name, boolean visible) {

Modified: felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/MethodCreator.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/MethodCreator.java?rev=1354636&r1=1354635&r2=1354636&view=diff
==============================================================================
--- felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/MethodCreator.java (original)
+++ felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/MethodCreator.java Wed Jun 27 17:20:17 2012
@@ -33,6 +33,7 @@ import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 import org.objectweb.asm.Type;
 import org.objectweb.asm.commons.GeneratorAdapter;
+import org.objectweb.asm.tree.LocalVariableNode;
 
 /**
  * iPOJO Class Adapter.
@@ -218,9 +219,9 @@ public class MethodCreator extends Class
 
         MethodDescriptor md = getMethodDescriptor(name, desc);
         if (md == null) {
-            generateMethodHeader(access, name, desc, signature, exceptions, null, null);
+            generateMethodHeader(access, name, desc, signature, exceptions, null, null, null);
         } else {
-            generateMethodHeader(access, name, desc, signature, exceptions, md.getAnnotations(), md.getParameterAnnotations());
+            generateMethodHeader(access, name, desc, signature, exceptions, md.getArgumentLocalVariables(), md.getAnnotations(), md.getParameterAnnotations());
         }
 
         String id = generateMethodFlag(name, desc);
@@ -356,12 +357,22 @@ public class MethodCreator extends Class
      * @param desc : method descriptor.
      * @param signature : method signature.
      * @param exceptions : declared exceptions.
+     * @param localVariables : the local variable nodes.
      * @param annotations : the annotations to move to this method.
      * @param paramAnnotations : the parameter annotations to move to this method.
      */
-    private void generateMethodHeader(int access, String name, String desc, String signature, String[] exceptions, List<AnnotationDescriptor> annotations, Map<Integer, List<AnnotationDescriptor>> paramAnnotations) {
+    private void generateMethodHeader(int access, String name, String desc, String signature, String[] exceptions, List<LocalVariableNode> localVariables, List<AnnotationDescriptor> annotations, Map<Integer, List<AnnotationDescriptor>> paramAnnotations) {
         GeneratorAdapter mv = new GeneratorAdapter(cv.visitMethod(access, name, desc, signature, exceptions), access, name, desc);
 
+        // If we have variables, we wraps the code within labels. The `lifetime` of the variables are bound to those
+        // two variables.
+        boolean hasArgumentLabels = localVariables != null && !localVariables.isEmpty();
+        Label start = null;
+        if (hasArgumentLabels) {
+            start = new Label();
+            mv.visitLabel(start);
+        }
+
         mv.visitCode();
 
         Type returnType = Type.getReturnType(desc);
@@ -449,6 +460,13 @@ public class MethodCreator extends Class
         }
         mv.visitInsn(returnType.getOpcode(IRETURN));
 
+        // If we had arguments, we mark the end of the lifetime.
+        Label end = null;
+        if (hasArgumentLabels) {
+            end = new Label();
+            mv.visitLabel(end);
+        }
+
         // Move annotations
         if (annotations != null) {
             for (int i = 0; i < annotations.size(); i++) {
@@ -470,6 +488,13 @@ public class MethodCreator extends Class
             }
         }
 
+        // Write the arguments name.
+        if (hasArgumentLabels) {
+            for (LocalVariableNode var : localVariables) {
+                mv.visitLocalVariable(var.name, var.desc, var.signature, start, end, var.index);
+            }
+        }
+
         mv.visitMaxs(0, 0);
         mv.visitEnd();
     }

Modified: felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/MethodDescriptor.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/MethodDescriptor.java?rev=1354636&r1=1354635&r2=1354636&view=diff
==============================================================================
--- felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/MethodDescriptor.java (original)
+++ felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/MethodDescriptor.java Wed Jun 27 17:20:17 2012
@@ -19,14 +19,16 @@
 package org.apache.felix.ipojo.manipulation;
 
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-
 import org.apache.felix.ipojo.manipulation.ClassChecker.AnnotationDescriptor;
 import org.apache.felix.ipojo.metadata.Attribute;
 import org.apache.felix.ipojo.metadata.Element;
 import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.LocalVariableNode;
 
 /**
  * Method Descriptor describe a method.
@@ -67,21 +69,47 @@ public class MethodDescriptor {
     private Map<Integer, List<AnnotationDescriptor>> m_parameterAnnotations = new HashMap<Integer, List<AnnotationDescriptor>>();
 
     /**
+     * The arguments variables.
+     */
+    private List<LocalVariableNode> m_argLocalVariables;
+
+    /**
+     * The stack size to keep of the arguments.
+     */
+    private final int m_argsVarLength;
+
+    /**
+     * Flag indicating is the described method is static.
+     */
+    private final boolean m_isStatic;
+
+    /**
      * Constructor.
      * @param name : name of the method.
      * @param desc : descriptor of the method.
+     * @param isStatic : is the method static
      */
-    public MethodDescriptor(String name, String desc) {
+    public MethodDescriptor(String name, String desc, boolean isStatic) {
         m_name = name;
         m_desc = desc;
+        m_isStatic = isStatic;
         Type ret = Type.getReturnType(desc);
         Type[] args = Type.getArgumentTypes(desc);
 
         m_returnType = getType(ret);
         m_arguments = new String[args.length];
+        int argsVarLength = args.length;
+        if (!m_isStatic) {
+            argsVarLength++;
+        }
         for (int i = 0; i < args.length; i++) {
-            m_arguments[i] = getType(args[i]);
+            String type = getType(args[i]);
+            m_arguments[i] = type;
+            if ("long".equals(type) || "double".equals(type)) {
+                argsVarLength++;
+            }
         }
+        m_argsVarLength = argsVarLength;
     }
 
     /**
@@ -186,4 +214,30 @@ public class MethodDescriptor {
         return m_name;
     }
 
+    public void addLocalVariable(String name, String desc, String signature, int index) {
+        if (index >= m_argsVarLength) {
+            // keep only argument-related local variables definitions (others relate to code which isn't in this method) 
+            return;
+        }
+        if (m_argLocalVariables == null) {
+            m_argLocalVariables = new ArrayList<LocalVariableNode>();
+        }
+        m_argLocalVariables.add(new LocalVariableNode(name, desc, signature, null, null, index));
+    }
+
+    public void end() {
+        if (m_argLocalVariables != null && m_argLocalVariables.size() > 1) {
+            // sort them by index, even if from experience, argument-related variables (and only those) are already sorted
+            Collections.sort(m_argLocalVariables, new Comparator<LocalVariableNode>(){
+                public int compare(LocalVariableNode o1, LocalVariableNode o2) {
+                    return o1.index - o2.index;
+                }
+            });
+        }
+    }
+
+    public List<LocalVariableNode> getArgumentLocalVariables() {
+        return m_argLocalVariables;
+    }
+
 }