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 2007/09/27 14:47:55 UTC

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

Author: clement
Date: Thu Sep 27 05:47:53 2007
New Revision: 579994

URL: http://svn.apache.org/viewvc?rev=579994&view=rev
Log:
New annotation processor. The manipulator manages custom annotations (provided by external handlers).

Added:
    felix/trunk/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/CustomAnnotationVisitor.java
Removed:
    felix/trunk/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Attribute.java
    felix/trunk/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Element.java
    felix/trunk/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/SubElement.java
Modified:
    felix/trunk/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Controller.java
    felix/trunk/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Provides.java
    felix/trunk/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/FieldCollector.java
    felix/trunk/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MetadataCollector.java
    felix/trunk/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MethodCollector.java

Modified: felix/trunk/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Controller.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Controller.java?rev=579994&r1=579993&r2=579994&view=diff
==============================================================================
--- felix/trunk/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Controller.java (original)
+++ felix/trunk/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Controller.java Thu Sep 27 05:47:53 2007
@@ -28,6 +28,5 @@
 @Target(ElementType.FIELD)
 public @interface Controller {
     
-    
 
 }

Modified: felix/trunk/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Provides.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Provides.java?rev=579994&r1=579993&r2=579994&view=diff
==============================================================================
--- felix/trunk/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Provides.java (original)
+++ felix/trunk/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Provides.java Thu Sep 27 05:47:53 2007
@@ -32,7 +32,7 @@
      * Set the provided specifications.
      * Default : all implemented interfaces
      */
-    String specification() default "";
+    Class[] specifications() default { };
     
     /**
      * Set the service object creation policy.

Added: felix/trunk/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/CustomAnnotationVisitor.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/CustomAnnotationVisitor.java?rev=579994&view=auto
==============================================================================
--- felix/trunk/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/CustomAnnotationVisitor.java (added)
+++ felix/trunk/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/CustomAnnotationVisitor.java Thu Sep 27 05:47:53 2007
@@ -0,0 +1,237 @@
+/* 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.ipojo.manipulation.annotations;
+
+import java.lang.reflect.Array;
+
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.commons.EmptyVisitor;
+
+/**
+ * Collect metadata from custom annotation.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class CustomAnnotationVisitor extends EmptyVisitor implements AnnotationVisitor {
+
+    /**
+     * PArent element.
+     */
+    private Element m_elem;
+
+    /**
+     * Id attribute (if found).
+     */
+    private String m_id;
+
+    /**
+     * Parent attribute (if found).
+     */
+    private String m_parent;
+
+    /**
+     * Is the custom annotation a first-order annotation.
+     */
+    private boolean m_root;
+
+    /**
+     * MEtadata collector.
+     */
+    private MetadataCollector m_collector;
+    
+    /**
+     * Constructor.
+     * @param elem : parent element
+     * @param collector : metadata collector
+     * @param root : is the annotation a root
+     */
+    public CustomAnnotationVisitor(Element elem, MetadataCollector collector, boolean root) {
+        m_elem = elem;
+        m_root = root;
+        m_collector = collector;
+    }
+    
+    /**
+     * Check if the given annotation descriptor is an iPOJO custom annotation.
+     * A valid iPOJO custom annotation must contains 'ipojo' or 'handler' in its qualified name.
+     * @param desc : annotation descriptor
+     * @return : true if the given descriptor is an iPOJO custom annotation
+     */
+    public static boolean isCustomAnnotation(String desc) {
+        desc = desc.toLowerCase();
+        if (desc.indexOf("ipojo") != -1 || desc.indexOf("handler") != -1) {
+            return true;
+        }
+        return false;
+    }
+    
+    /**
+     * Build the element object from the given descriptor.
+     * @param desc : annotation descriptor
+     * @return : the element
+     */
+    public static Element buildElement(String desc) {
+        String s = (desc.replace('/', '.')).substring(1, desc.length() - 1);
+        int index = s.lastIndexOf('.');
+        String name = s.substring(index + 1);
+        String namespace = s.substring(0, index);
+        return new Element(name, namespace);
+    }
+
+    /**
+     * Visit an 'simple' annotation attribute.
+     * This method is used for primitive arrays too. 
+     * @param arg0 : attribute name
+     * @param arg1 : attribute value
+     * @see org.objectweb.asm.commons.EmptyVisitor#visit(java.lang.String, java.lang.Object)
+     */
+    public void visit(String arg0, Object arg1) {
+        if (arg1.getClass().isArray()) {
+            // Primitive arrays case
+            String v = null;
+            int index = Array.getLength(arg1);
+            for (int i = 0; i < index; i++) {
+                if (v == null) {
+                    v = "{" + Array.get(arg1, i);
+                } else {
+                    v += "," + Array.get(arg1, i);
+                }
+            }
+            v += "}";
+            m_elem.addAttribute(new Attribute(arg0, v));
+            return;
+        }
+        // Attributes are added as normal attributes
+        m_elem.addAttribute(new Attribute(arg0, arg1.toString()));
+        if (m_root) {
+            if (arg0.equals("id")) {
+                m_id = arg1.toString();
+            } else if (arg0.equals("parent")) {
+                m_parent = arg1.toString();
+            }
+        }
+    }
+
+    /**
+     * Visit a sub-annotation.
+     * @param arg0 : attribute name.
+     * @param arg1 : annotation description
+     * @return an annotation visitor which will visit the given annotation
+     * @see org.objectweb.asm.commons.EmptyVisitor#visitAnnotation(java.lang.String, java.lang.String)
+     */
+    public AnnotationVisitor visitAnnotation(String arg0, String arg1) {
+        // Sub annotations are mapped to sub-elements
+        Element elem = buildElement(arg1);
+        m_elem.addElement(elem);
+        return new CustomAnnotationVisitor(elem, m_collector, false);
+    }
+
+    /**
+     * Visit an array attribute.
+     * @param arg0 : attribute name
+     * @return a visitor which will visit each element of the array
+     * @see org.objectweb.asm.commons.EmptyVisitor#visitArray(java.lang.String)
+     */
+    public AnnotationVisitor visitArray(String arg0) {
+        return new SubArrayVisitor(m_elem, arg0);
+    }
+
+    /**
+     * End of the visit.
+     * All attribute was visited, we can update collectors data.
+     * @see org.objectweb.asm.commons.EmptyVisitor#visitEnd()
+     */
+    public void visitEnd() {
+        if (m_root) {
+            if (m_id != null) {
+                m_collector.getIds().put(m_id, m_elem);
+            }
+            m_collector.getElements().put(m_elem, m_parent);
+        }
+    }
+
+    private class SubArrayVisitor extends EmptyVisitor implements AnnotationVisitor {
+        /**
+         * Parent element.
+         */
+        private Element m_elem;
+
+        /**
+         * Attribute name.
+         */
+        private String m_name;
+
+        /**
+         * Attribute value.
+         * (accumulator)
+         */
+        private String m_acc;
+
+        /**
+         * Constructor.
+         * @param elem : parent element.
+         * @param name : attribute name.
+         */
+        public SubArrayVisitor(Element elem, String name) {
+            m_elem = elem;
+            m_name = name;
+        }
+
+        /**
+         * Visit a 'simple' element of the visited array.
+         * @param arg0 : null
+         * @param arg1 : element value.
+         * @see org.objectweb.asm.commons.EmptyVisitor#visit(java.lang.String, java.lang.Object)
+         */
+        public void visit(String arg0, Object arg1) {
+            if (m_acc == null) {
+                m_acc = "{" + arg1.toString();
+            } else {
+                m_acc = m_acc + "," + arg1.toString();
+            }
+        }
+
+        /**
+         * Visit an annotation element of the visited array.
+         * @param arg0 : null
+         * @param arg1 : annotation to visit
+         * @return the visitor which will visit the annotation
+         * @see org.objectweb.asm.commons.EmptyVisitor#visitAnnotation(java.lang.String, java.lang.String)
+         */
+        public AnnotationVisitor visitAnnotation(String arg0, String arg1) {
+            // Sub annotations are map to sub-elements
+            Element elem = buildElement(arg1);
+            m_elem.addElement(elem);
+            return new CustomAnnotationVisitor(elem, m_collector, false);
+        }
+
+        /**
+         * End of the visit.
+         * @see org.objectweb.asm.commons.EmptyVisitor#visitEnd()
+         */
+        public void visitEnd() {
+            if (m_acc != null) {
+                // We have analyzed an attribute
+                m_elem.addAttribute(new Attribute(m_name, m_acc + "}"));
+            }
+        }
+
+    }
+}

Modified: felix/trunk/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/FieldCollector.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/FieldCollector.java?rev=579994&r1=579993&r2=579994&view=diff
==============================================================================
--- felix/trunk/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/FieldCollector.java (original)
+++ felix/trunk/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/FieldCollector.java Thu Sep 27 05:47:53 2007
@@ -33,7 +33,7 @@
     /**
      * Collected element.
      */
-    private Element m_element;
+    private MetadataCollector m_collector;
     
     /**
      * Field name. 
@@ -43,10 +43,10 @@
     /**
      * Constructor.
      * @param fieldName : field name
-     * @param elem : element on which append the collected metadata.
+     * @param collector : metadata collector.
      */
-    public FieldCollector(String fieldName, Element elem) {
-        m_element = elem;
+    public FieldCollector(String fieldName, MetadataCollector collector) {
+        m_collector = collector;
         m_field = fieldName;
     }
 
@@ -61,23 +61,41 @@
         if (arg0.equals("Lorg/apache/felix/ipojo/annotations/Requires;")) {
             return new RequiresAnnotationParser(m_field);
         }
+        if (arg0.equals("Lorg/apache/felix/ipojo/annotations/Controller;")) {
+            Element elem = new Element("controller", "");
+            elem.addAttribute(new Attribute("field", m_field));
+            m_collector.getElements().put(elem, null);
+            return null;
+        }
         if (arg0.equals("Lorg/apache/felix/ipojo/annotations/ServiceProperty;")) {
-            if (m_element.getElements("Provides", "").length == 0) {
+            if (! m_collector.getIds().containsKey("provides")) { // The provides annotation is already computed.
                 System.err.println("The component does not provide services, skip ServiceProperty for " + m_field);
                 return null;
+            } else {
+                // Get the provides element
+                Element parent = (Element) m_collector.getIds().get("provides");
+                return new PropertyAnnotationParser(m_field, parent);
             }
-            Element provides = m_element.getElements("Provides", "")[0];
-            return new PropertyAnnotationParser(provides, m_field);
+            
         }
         if (arg0.equals("Lorg/apache/felix/ipojo/annotations/Property;")) {
             Element parent = null;
-            if (m_element.getElements("Properties", "").length == 0) {
+            if (! m_collector.getIds().containsKey("properties")) {
                 parent = new Element("Properties", "");
-                m_element.addElement(parent);
-            }
-            parent = m_element.getElements("Properties", "")[0];
-            return new PropertyAnnotationParser(parent, m_field);
+                m_collector.getIds().put("properties", parent);
+                m_collector.getElements().put(parent, null);
+            } else {
+                parent = (Element) m_collector.getIds().get("properties");
+            }
+            return new PropertyAnnotationParser(m_field, parent);
+        }
+        
+        if (CustomAnnotationVisitor.isCustomAnnotation(arg0)) {
+            Element elem = CustomAnnotationVisitor.buildElement(arg0);
+            elem.addAttribute(new Attribute("field", m_field)); // Add a field attribute
+            return new CustomAnnotationVisitor(elem, m_collector, true);
         }
+        
         return null;
        
     }
@@ -155,20 +173,18 @@
          * Create a "requires" element
          * @see org.objectweb.asm.AnnotationVisitor#visitEnd()
          */
-        public void visitEnd() { 
-         // Check if it is a full-determined requirement
+        public void visitEnd() {
             Element req = null;
-            Element[] reqs = m_element.getElements("requires");
-            for (int i = 0; i < reqs.length; i++) {
-                if (reqs[i].containsAttribute("id") && (reqs[i].getAttribute("id").equals(m_id) || reqs[i].getAttribute("id").equals(m_field))) {
-                    req = reqs[i];
-                    break;
-                }
+            if (m_id == null) {
+                req = (Element) m_collector.getIds().get(m_field);
+            } else {
+                req = (Element) m_collector.getIds().get(m_id);
             }
+
             if (req == null) {
-                // Add the complete requires
                 req = new Element("requires", "");
             }
+
             req.addAttribute(new Attribute("field", m_field));
             if (m_specification != null) {
                 req.addAttribute(new Attribute("interface", m_specification));
@@ -185,7 +201,15 @@
             if (m_id != null) {
                 req.addAttribute(new Attribute("id", m_id));
             }
-            m_element.addElement(req);
+            
+            if (m_id != null) { 
+                m_collector.getIds().put(m_id, req);
+            } else {
+                m_collector.getIds().put(m_field, req);
+            }
+            
+            m_collector.getElements().put(req, null);
+                
             return;
         }
     }
@@ -196,7 +220,7 @@
     private final class PropertyAnnotationParser extends EmptyVisitor implements AnnotationVisitor {
         
         /**
-         * Parent element (element on which append collected metadata).
+         * Parent element element.
          */
         private Element m_parent;
         
@@ -221,7 +245,7 @@
          * @param parent : parent element.
          * @param field : field name.
          */
-        private PropertyAnnotationParser(Element parent, String field) {
+        private PropertyAnnotationParser(String field, Element parent) {
             m_parent = parent;
             m_field = field;
         }

Modified: felix/trunk/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MetadataCollector.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MetadataCollector.java?rev=579994&r1=579993&r2=579994&view=diff
==============================================================================
--- felix/trunk/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MetadataCollector.java (original)
+++ felix/trunk/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MetadataCollector.java Thu Sep 27 05:47:53 2007
@@ -18,12 +18,18 @@
  */
 package org.apache.felix.ipojo.manipulation.annotations;
 
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
 import org.apache.felix.ipojo.metadata.Attribute;
 import org.apache.felix.ipojo.metadata.Element;
 import org.objectweb.asm.AnnotationVisitor;
 import org.objectweb.asm.FieldVisitor;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
 import org.objectweb.asm.commons.EmptyVisitor;
 
 /**
@@ -48,6 +54,19 @@
      */
     private boolean m_containsAnnotation = false;
     
+    /**
+     * Map of [element ids, element].
+     * This map is used to easily get an already created element. 
+     */
+    private Map m_ids = new HashMap();
+    
+    /**
+     * Map of [element, referto].
+     * This map is used to recreate the element hierarchie.
+     * Stored element are added under referred element. 
+     */
+    private Map m_elements = new HashMap();
+    
     public Element getElem() {
         return m_elem;
     }
@@ -55,6 +74,7 @@
     public boolean isAnnotated() {
         return m_containsAnnotation;
     }
+    
 
     /**
      * Start visiting a class.
@@ -68,6 +88,8 @@
      * @see org.objectweb.asm.ClassAdapter#visit(int, int, java.lang.String, java.lang.String, java.lang.String, java.lang.String[])
      */
     public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
+        m_ids = new HashMap();
+        m_elements = new HashMap();
         m_className = name;
     }
 
@@ -94,13 +116,15 @@
             return new ProvidesVisitor();
         }
         
-        //@Element
-        if (desc.equals("Lorg/apache/felix/ipojo/annotations/Element;")) {
-            return new ElementVisitor(m_elem);
+        if (CustomAnnotationVisitor.isCustomAnnotation(desc)) {
+            Element elem = CustomAnnotationVisitor.buildElement(desc);
+            return new CustomAnnotationVisitor(elem, this, true);
         }
         
         return null;
     }
+    
+
 
     /**
      * Visit a field.
@@ -114,7 +138,7 @@
      * @see org.objectweb.asm.ClassAdapter#visitField(int, java.lang.String, java.lang.String, java.lang.String, java.lang.Object)
      */
     public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
-        return new FieldCollector(name, m_elem);
+        return new FieldCollector(name, this);
     }
 
     /**
@@ -129,10 +153,42 @@
      * @see org.objectweb.asm.ClassAdapter#visitMethod(int, java.lang.String, java.lang.String, java.lang.String, java.lang.String[])
      */
     public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
-        return new MethodCollector(name, m_elem);
+        return new MethodCollector(name, this);
     }
     
     /**
+     * End of the visit : compute final elements.
+     * @see org.objectweb.asm.commons.EmptyVisitor#visitEnd()
+     */
+    public void visitEnd() {
+        // Recompute the tree
+        Set elems = getElements().keySet();
+        Iterator it = elems.iterator();
+        while (it.hasNext()) {
+            Element current = (Element) it.next();
+            String reference = (String) getElements().get(current);
+            if (reference == null) {
+                m_elem.addElement(current);
+            } else {
+                Element ref = (Element) getIds().get(reference);
+                if (ref == null) {
+                    System.err.println("The element " + reference + " is not declared - skip the element " + current.toXMLString());
+                } else {
+                    ref.addElement(current);
+                }
+            }
+        }
+    }
+
+    protected Map getIds() {
+        return m_ids;
+    }
+
+    protected Map getElements() {
+        return m_elements;
+    }
+
+    /**
      * Parse the @provides annotation.
      */
     private class ProvidesVisitor extends EmptyVisitor implements AnnotationVisitor {
@@ -148,21 +204,64 @@
          * @see org.objectweb.asm.commons.EmptyVisitor#visit(java.lang.String, java.lang.Object)
          */
         public void visit(String arg0, Object arg1) {
-            if (arg0.equals("specifications")) {
-                m_prov.addAttribute(new Attribute("interface", arg1.toString()));
-            }
             if (arg0.equals("factory")) {
                 m_prov.addAttribute(new Attribute("factory", arg1.toString()));
             }
         }
         
         /**
+         * Visit specifications array.
+         * @param arg0 : attribute name
+         * @return a visitor visiting each element of the array.
+         * @see org.objectweb.asm.commons.EmptyVisitor#visitArray(java.lang.String)
+         */
+        public AnnotationVisitor visitArray(String arg0) {
+            if (arg0.equals("specifications")) {
+                return new InterfaceArrayVisitor();
+            } else {
+                return null;
+            }
+        }
+        
+        /**
          * End of the visit.
          * Append to the parent element the computed "provides" element.
          * @see org.objectweb.asm.commons.EmptyVisitor#visitEnd()
          */
         public void visitEnd() {
-            m_elem.addElement(m_prov);            
+            getIds().put("provides", m_prov);
+            getElements().put(m_prov, null);
+        }
+        
+        private class InterfaceArrayVisitor extends EmptyVisitor {
+            /**
+             * List of parsed interface.
+             */
+            private String m_itfs;
+            
+            /**
+             * Visit one element of the array.
+             * @param arg0 : null
+             * @param arg1 : element value.
+             * @see org.objectweb.asm.commons.EmptyVisitor#visit(java.lang.String, java.lang.Object)
+             */
+            public void visit(String arg0, Object arg1) {
+                if (m_itfs == null) {
+                    m_itfs = "{" + ((Type) arg1).getClassName();
+                } else {
+                    m_itfs += "," + ((Type) arg1).getClassName();
+                }
+            }
+            
+            /**
+             * End of the array visit.
+             * Add the attribute to 'provides' element.
+             * @see org.objectweb.asm.commons.EmptyVisitor#visitEnd()
+             */
+            public void visitEnd() {
+                m_prov.addAttribute(new Attribute("interface", m_itfs + "}"));
+            }
+            
         }
         
     }
@@ -250,164 +349,9 @@
             if (m_propagation != null) {
                 Element props = new Element("properties", "");
                 props.addAttribute(new Attribute("propagation", m_propagation));
-                m_elem.addElement(props);
+                getIds().put("properties", props);
+                getElements().put(props, null);
             }
-        }        
-    }
-
-    /**
-     * Parse the @Element & @SubElement annotations. 
-     */
-    private class ElementVisitor extends EmptyVisitor implements AnnotationVisitor {
-        
-        /**
-         * Element name.
-         */
-        private String m_name;
-        
-        /**
-         * Element namespace. 
-         */
-        private String m_namespace;
-        
-        /**
-         * Parent Element. 
-         */
-        private Element m_parent;
-        
-        /**
-         * Accumulator element to store temporary attributes and sub-elements.
-         */
-        private Element m_accu = new Element("accu", "");
-        
-        /**
-         * Constructor.
-         * @param parent : parent element.
-         */
-        public ElementVisitor(Element parent) {
-            m_parent = parent;
-        }
-
-        /**
-         * Visit annotation attribute.
-         * @param arg0 : name of the attribute
-         * @param arg1 : value of the attribute
-         * @see org.objectweb.asm.AnnotationVisitor#visit(java.lang.String, java.lang.Object)
-         */
-        public void visit(String arg0, Object arg1) {
-            if (arg0.equals("name")) {
-                m_name = arg1.toString();
-            }
-            if (arg0.equals("namespace")) {
-                m_namespace = arg1.toString();
-            }
-        }
-
-        
-        /**
-         * Visit array annotation attribute (attributes & elements).
-         * @param arg0 : attribute name
-         * @return the annotation visitor which will visit the content of the array
-         * @see org.objectweb.asm.AnnotationVisitor#visitArray(java.lang.String)
-         */
-        public AnnotationVisitor visitArray(String arg0) {
-            if (arg0.equals("attributes")) {
-                return new EmptyVisitor() {
-                    public AnnotationVisitor visitAnnotation(String arg0, String arg1) {
-                        return new AttributeVisitor(m_accu);
-                    }
-                    
-                };
-            }
-            if (arg0.equals("elements")) {
-                return new EmptyVisitor() {
-                    public AnnotationVisitor visitAnnotation(String arg0, String arg1) {
-                        return new ElementVisitor(m_accu);
-                    }
-                    
-                };
-            }
-            return null;
-        }
-
-        /**
-         * End of the visit.
-         * Append computed element to the parent element.
-         * @see org.objectweb.asm.AnnotationVisitor#visitEnd()
-         */
-        public void visitEnd() {
-            Element elem = null;
-            if (m_namespace != null) {
-                elem = new Element(m_name, m_namespace);
-            } else {
-                elem = new Element(m_name, "");
-            }
-
-            Attribute[] atts = m_accu.getAttributes();
-            for (int i = 0; i < atts.length; i++) {
-                elem.addAttribute(atts[i]);
-            }
-
-            Element[] elems = m_accu.getElements();
-            for (int i = 0; i < elems.length; i++) {
-                elem.addElement(elems[i]);
-            }
-
-            m_parent.addElement(elem);
-        }
-        
-    }
-    
-    /**
-     * Parse an @attribute annotation.
-     */
-    private class AttributeVisitor extends EmptyVisitor implements AnnotationVisitor {
-        /**
-         * Parent element.
-         */
-        private Element m_parent;
-
-        /**
-         * Attribute name.
-         */
-        private String m_name;
-        
-        /**
-         * Attribute value. 
-         */
-        private String m_value;
-        
-        /**
-         * Constructor.
-         * @param parent : parent element.
-         */
-        public AttributeVisitor(Element parent) {
-            m_parent = parent;
-        }
-
-        /**
-         * Visit attributes. 
-         * @param arg0 : attribute name
-         * @param arg1 : attribute value
-         * @see org.objectweb.asm.commons.EmptyVisitor#visit(java.lang.String, java.lang.Object)
-         */
-        public void visit(String arg0, Object arg1) {
-            if (arg0.equals("name")) {
-                m_name = arg1.toString();
-                return;
-            }
-            if (arg0.equals("value")) {
-                m_value = arg1.toString();
-            }
-        }
-
-        /**
-         * End of the visit.
-         * Append this current attribute to the parent element.
-         * @see org.objectweb.asm.commons.EmptyVisitor#visitEnd()
-         */
-        public void visitEnd() {
-            m_parent.addAttribute(new Attribute(m_name, m_value));
         }        
     }
 }

Modified: felix/trunk/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MethodCollector.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MethodCollector.java?rev=579994&r1=579993&r2=579994&view=diff
==============================================================================
--- felix/trunk/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MethodCollector.java (original)
+++ felix/trunk/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MethodCollector.java Thu Sep 27 05:47:53 2007
@@ -30,9 +30,9 @@
 public class MethodCollector extends EmptyVisitor {
 
     /**
-     * Parent element (component).
+     * Parent collector.
      */
-    private Element m_element;
+    private MetadataCollector m_collector;
     
     /**
      * Method name. 
@@ -42,10 +42,10 @@
     /**
      * Constructor.
      * @param name : name of the method.
-     * @param element : parent element.
+     * @param collector : parent collector.
      */
-    public MethodCollector(String name, Element element) {
-        m_element = element;
+    public MethodCollector(String name, MetadataCollector collector) {
+        m_collector = collector;
         m_name = name;
     }
 
@@ -75,6 +75,13 @@
         if (arg0.equals("Lorg/apache/felix/ipojo/annotations/Unbind;")) {
             return processBind("unbind");
         }
+        
+        if (CustomAnnotationVisitor.isCustomAnnotation(arg0)) {
+            Element elem = CustomAnnotationVisitor.buildElement(arg0);
+            elem.addAttribute(new Attribute("method", m_name));
+            return new CustomAnnotationVisitor(elem, m_collector, true);
+        }
+        
         return null;
     }
 
@@ -95,7 +102,7 @@
         Element cb = new Element("callback", "");
         cb.addAttribute(new org.apache.felix.ipojo.metadata.Attribute("transition", "validate"));
         cb.addAttribute(new org.apache.felix.ipojo.metadata.Attribute("method", m_name));
-        m_element.addElement(cb);
+        m_collector.getElements().put(cb, null);
         return null;
     }
 
@@ -107,7 +114,7 @@
         Element cb = new Element("callback", "");
         cb.addAttribute(new org.apache.felix.ipojo.metadata.Attribute("transition", "invalidate"));
         cb.addAttribute(new org.apache.felix.ipojo.metadata.Attribute("method", m_name));
-        m_element.addElement(cb);
+        m_collector.getElements().put(cb, null);
         return null;
     }
 
@@ -116,12 +123,13 @@
      * @return the visitor parsing the visited annotation.
      */
     private AnnotationVisitor processServiceProperty() {
-        if (m_element.getElements("Provides", "").length == 0) {
+        if (! m_collector.getIds().containsKey("provides")) {
             System.err.println("the component does not provide services, skip ServiceProperty for " + m_name);
             return null;
+        } else {
+            Element provides = (Element) m_collector.getIds().get("provides");
+            return new PropertyAnnotationParser(provides, m_name);
         }
-        Element provides = m_element.getElements("Provides", "")[0];
-        return new PropertyAnnotationParser(provides, m_name);
     }
 
     /**
@@ -129,11 +137,15 @@
      * @return the visitor parsing the visited annotation.
      */
     private AnnotationVisitor processProperty() {
-        if (m_element.getElements("Properties", "").length == 0) {
-            m_element.addElement(new Element("Properties", ""));
+        Element prop = null;
+        if (! m_collector.getIds().containsKey("properties")) {
+            prop = new Element("Properties", "");
+            m_collector.getIds().put("properties", prop);
+            m_collector.getElements().put(prop, null);
+        } else {
+            prop = (Element) m_collector.getIds().get("properties");
         }
-        Element props = m_element.getElements("Properties", "")[0];
-        return new PropertyAnnotationParser(props, m_name);
+        return new PropertyAnnotationParser(prop, m_name);
     }
 
     /**
@@ -232,18 +244,7 @@
                 }
             }
             // Check if it is a full-determined requirement
-            Element req = null;
-            Element[] reqs = m_element.getElements("requires");
-            for (int i = 0; i < reqs.length; i++) {
-                if (reqs[i].containsAttribute("id") && reqs[i].getAttribute("id").equals(m_id)) {
-                    req = reqs[i];
-                    break;
-                }
-                if (reqs[i].containsAttribute("field") && reqs[i].getAttribute("field").equals(m_id)) {
-                    req = reqs[i];
-                    break;
-                }
-            }
+            Element req = (Element) m_collector.getIds().get(m_id);
             if (req == null) {
                 // Add the complete requires
                 req = new Element("requires", "");
@@ -267,7 +268,8 @@
             method.addAttribute(new Attribute("method", m_name));
             method.addAttribute(new Attribute("type", m_type));
             req.addElement(method);
-            m_element.addElement(req);
+            m_collector.getIds().put(m_id, req);
+            m_collector.getElements().put(req, null);
             return;
         }
     }