FELIX-4215 Extend manipulation metadata with argument names

Extract argument's name from the byte code (local variables) and extends the MethodMetadata to handle them.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1520078 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/MethodDescriptor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/MethodDescriptor.java
index 84509ea..a477560 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/MethodDescriptor.java
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/MethodDescriptor.java
@@ -19,12 +19,8 @@
 

 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 java.util.*;

+

 import org.apache.felix.ipojo.manipulation.ClassChecker.AnnotationDescriptor;

 import org.apache.felix.ipojo.metadata.Attribute;

 import org.apache.felix.ipojo.metadata.Element;

@@ -85,6 +81,12 @@
     private final boolean m_isStatic;

 

     /**

+     * The local variables by index.

+     * This map is used to detect the argument names.

+     */

+    private LinkedHashMap<Integer, LocalVariableNode> m_locals = new LinkedHashMap<Integer, LocalVariableNode>();

+

+    /**

      * Constructor.

      * @param name : name of the method.

      * @param desc : descriptor of the method.

@@ -164,13 +166,23 @@
 

         // Add arguments

         if (m_arguments.length > 0) {

-            StringBuffer args = new StringBuffer("{");

+            StringBuilder args = new StringBuilder("{");

+            StringBuilder names = new StringBuilder("{");

             args.append(m_arguments[0]);

+            if (m_locals.containsKey(1)) {

+                names.append(m_locals.get(1).name); // index +1 as the 0 is this

+            }

             for (int i = 1; i < m_arguments.length; i++) {

-                args.append("," + m_arguments[i]);

+                args.append(",").append(m_arguments[i]);

+                if (m_locals.containsKey(i +1)) {

+                    names.append(",").append(m_locals.get(i +1).name);

+                }

             }

             args.append("}");

+            names.append("}");

+

             method.addAttribute(new Attribute("arguments", args.toString()));

+            method.addAttribute(new Attribute("names", names.toString()));

         }

 

         return method;

@@ -221,6 +233,7 @@
     }

 

     public void addLocalVariable(String name, String desc, String signature, int index) {

+        m_locals.put(index, new LocalVariableNode(name, desc, signature, null, null, index));

         if (index >= m_argsVarLength) {

             // keep only argument-related local variables definitions (others relate to code which isn't in this method) 

             return;

diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/parser/MethodMetadata.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/parser/MethodMetadata.java
index eb2e9eb..0002611 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/parser/MethodMetadata.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/parser/MethodMetadata.java
@@ -20,6 +20,8 @@
 
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
+import java.util.LinkedHashMap;
+import java.util.Map;
 
 import org.apache.felix.ipojo.InstanceManager;
 import org.apache.felix.ipojo.metadata.Element;
@@ -47,20 +49,27 @@
      */
     public static final String CONSTRUCTOR_PREFIX = "$init";
 
+
     /**
      * The name of the method.
      */
-    private String m_name;
+    private final String m_name;
 
     /**
      * The argument type array.
      */
-    private String[] m_arguments = new String[0];
+    private final String[] m_arguments;
 
     /**
      * The returned type.
      */
-    private String m_return = "void";
+    private final String m_return;
+
+    /**
+     * The argument names if there were contained in the manifest.
+     * @since 1.10.2
+     */
+    private final String[] m_names;
 
     /**
      * Creates a Method Metadata.
@@ -69,12 +78,23 @@
     MethodMetadata(Element metadata) {
         m_name = metadata.getAttribute("name");
         String arg = metadata.getAttribute("arguments");
+        String names = metadata.getAttribute("names");
         String result = metadata.getAttribute("return");
         if (arg != null) {
             m_arguments = ParseUtils.parseArrays(arg);
+        } else {
+            m_arguments = new String[0];
         }
+        if (names != null) {
+            m_names = ParseUtils.parseArrays(names);
+        } else {
+            m_names = new String[0];
+        }
+
         if (result != null) {
             m_return = result;
+        } else {
+            m_return = "void";
         }
     }
 
@@ -86,6 +106,24 @@
         return m_arguments;
     }
 
+    public String[] getMethodArgumentNames() {
+        return m_names;
+    }
+
+    /**
+     * Gets the method arguments.
+     * The keys are the argument names, while the values are the argument type.
+     * @return the map of argument
+     * @since 1.10.2
+     */
+    public Map<String, String> getArguments() {
+        LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
+        for (int i = 0; i < m_names.length; i++) {
+            map.put(m_names[i], m_arguments[i]);
+        }
+        return map;
+    }
+
     public String getMethodReturn() {
         return m_return;
     }