Add the processing of the Instantiate annotation (FELIX-1940)

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@892615 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MetadataCollector.java b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MetadataCollector.java
index 4de1e58..0355084 100644
--- a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MetadataCollector.java
+++ b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MetadataCollector.java
@@ -1,4 +1,4 @@
-/*
+/* 
  * 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
@@ -63,8 +63,8 @@
     /**
      * True if the visited class is a component type declaration (i.e. contains the @component annotation).
      */
-    private boolean m_containsAnnotation = false;
-
+    private boolean m_containsComponentAnnotation = false;
+    
     /**
      * Map of [element ids, element].
      * This map is used to easily get an already created element.
@@ -73,25 +73,34 @@
 
     /**
      * Map of [element, referto].
-     * This map is used to recreate the element hierarchie.
+     * This map is used to recreate the element hierarchy.
      * Stored element are added under referred element.
      */
     private Map m_elements = new HashMap();
+    
+    /**
+     * Instance declaration.
+     */
+    private Element m_instance;
 
     /**
      * XML document parser.
      */
     private DocumentBuilder m_builder;
 
-    public Element getElem() {
+
+    public Element getComponentTypeDeclaration() {
         return m_elem;
     }
-
-    public boolean isAnnotated() {
-        return m_containsAnnotation;
+    
+    public Element getInstanceDeclaration() {
+        return m_instance;
     }
-
-
+    
+    public boolean isComponentType() {
+        return m_containsComponentAnnotation;
+    }
+    
     /**
      * Start visiting a class.
      * Initialize the getter/setter generator, add the _cm field, add the pojo interface.
@@ -123,7 +132,7 @@
         if (desc.equals("Lorg/apache/felix/ipojo/annotations/Component;")) {
             // It is a component
             m_elem =  new Element("component", "");
-            m_containsAnnotation = true;
+            m_containsComponentAnnotation = true;
             m_elem.addAttribute(new Attribute("className", m_className.replace('/', '.')));
             return new ComponentVisitor();
         }
@@ -132,7 +141,7 @@
         if (desc.equals("Lorg/apache/felix/ipojo/annotations/Handler;")) {
             // It is a handler, change the root element
             m_elem = new Element("handler", "");
-            m_containsAnnotation = true;
+            m_containsComponentAnnotation = true;
             m_elem.addAttribute(new Attribute("classname", m_className.replace('/', '.')));
             return new HandlerVisitor();
         }
@@ -146,6 +155,11 @@
         if (desc.equals("Lorg/apache/felix/ipojo/annotations/HandlerDeclaration;")) {
             return new HandlerDeclarationVisitor();
         }
+        
+        // @Instantiate
+        if (desc.equals("Lorg/apache/felix/ipojo/annotations/Instantiate;")) {
+            return new InstantiateVisitor();
+        }
 
         if (CustomAnnotationVisitor.isCustomAnnotation(desc)) {
             Element elem = CustomAnnotationVisitor.buildElement(desc);
@@ -156,7 +170,6 @@
     }
 
 
-
     /**
      * Visit a field.
      * Call the field collector visitor.
@@ -327,7 +340,45 @@
         }
 
     }
+    
+    /**
+     * Parse the @Instantitate annotation.
+     */
+    private class InstantiateVisitor extends EmptyVisitor implements AnnotationVisitor {
+        /**
+         * Instance name. 
+         */
+        private String m_name;
+        
+        /**
+         * Visit an annotation attribute.
+         * @param arg0 the attribute name
+         * @param arg1 the 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;
+            }
+        }
+        
+        /**
+         * End of the visit. Creates the instance element.
+         * @see org.objectweb.asm.commons.EmptyVisitor#visitEnd()
+         */
+        public void visitEnd() {
+            m_instance = new Element("instance", "");
+            if (m_className != null) { // Should not be null.
+                m_instance.addAttribute(new Attribute("component", m_className));
+            }
+            if (m_name != null) {
+                m_instance.addAttribute(new Attribute("name", m_name));
+            }
+        }
+    }
 
+    
     /**
      * Parse the @component annotation.
      */
@@ -577,8 +628,7 @@
             // Add converted element as a root's child
             root.addElement(converted);
         }
-
-
     }
+
 }
 
diff --git a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/Pojoization.java b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/Pojoization.java
index a8dd373..6084bb4 100644
--- a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/Pojoization.java
+++ b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/Pojoization.java
@@ -28,6 +28,7 @@
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -76,7 +77,7 @@
     /**
      * Metadata (in internal format).
      */
-    private Element[] m_metadata = new Element[0];
+    private List/*Element*/ m_metadata = new ArrayList/*Element*/();
 
     /**
      * Errors which occur during the manipulation.
@@ -291,35 +292,37 @@
         ClassReader cr = new ClassReader(inC);
         MetadataCollector xml = new MetadataCollector();
         cr.accept(xml, 0);
-        if (xml.isAnnotated()) {
+        if (xml.isComponentType()) {
             boolean toskip = false;
-            for (int i = 0; !toskip && i < m_metadata.length; i++) {
-                if (! m_metadata[i].getName().equals("instance") // Only if its a component type definition, 
+            for (int i = 0; !toskip && i < m_metadata.size(); i++) {
+                Element meta = (Element)  m_metadata.get(i);
+                if (! meta.getName().equals("instance") // Only if its a component type definition, 
                                                                  // so skip instance declaration 
-                        && m_metadata[i].containsAttribute("name")
-                        && m_metadata[i].getAttribute("name").equalsIgnoreCase(xml.getElem().getAttribute("name"))) {
+                        && meta.containsAttribute("name")
+                        && meta.getAttribute("name").equalsIgnoreCase(xml.getComponentTypeDeclaration().getAttribute("name"))) {
                     toskip = true;
-                    warn("The component type " + xml.getElem().getAttribute("name") + " is overriden by the metadata file");
+                    warn("The component type " + xml.getComponentTypeDeclaration().getAttribute("name") + " is overriden by the metadata file");
                 }
             }
             if (!toskip) {
                 // if no metadata or empty one, create a new array.
-                if (m_metadata != null && m_metadata.length > 0) {
-                    Element[] newElementsList = new Element[m_metadata.length + 1];
-                    System.arraycopy(m_metadata, 0, newElementsList, 0, m_metadata.length);
-                    newElementsList[m_metadata.length] = xml.getElem();
-                    m_metadata = newElementsList;
-                } else {
-                    m_metadata = new Element[] { xml.getElem() };
-                }
-                String name = m_metadata[m_metadata.length - 1].getAttribute("classname");
+                Element elem = xml.getComponentTypeDeclaration();
+                m_metadata.add(elem);
+                
+                String name = elem.getAttribute("classname");
                 name = name.replace('.', '/');
                 name += ".class";
 
                 // Creates the ComponentInfo and store bytecode
-                ComponentInfo info = new ComponentInfo(name, m_metadata[m_metadata.length - 1]);
+                ComponentInfo info = new ComponentInfo(name, elem);
                 info.m_bytecode = inC;
                 m_components.add(info);
+                
+                // Instantiate ?
+                if (xml.getInstanceDeclaration() != null) {
+                    warn("Declaring an empty instance of " + elem.getAttribute("classname"));
+                    m_metadata.add(xml.getInstanceDeclaration());
+                }
             }
         }
     }
@@ -760,12 +763,13 @@
      */
     private void computeDeclaredComponents() {
         List componentClazzes = new ArrayList();
-        for (int i = 0; i < m_metadata.length; i++) {
-            String name = m_metadata[i].getAttribute("classname");
+        for (int i = 0; i < m_metadata.size(); i++) {
+            Element meta = (Element) m_metadata.get(i);
+            String name = meta.getAttribute("classname");
             if (name != null) { // Only handler and component have a classname attribute
                 name = name.replace('.', '/');
                 name += ".class";
-                componentClazzes.add(new ComponentInfo(name, m_metadata[i]));
+                componentClazzes.add(new ComponentInfo(name, meta));
             }
         }
         m_components = componentClazzes;
@@ -911,8 +915,9 @@
      */
     private void setPOJOMetadata(Attributes att) {
         StringBuffer meta = new StringBuffer();
-        for (int i = 0; i < m_metadata.length; i++) {
-            meta.append(buildManifestMetadata(m_metadata[i], new StringBuffer()));
+        for (int i = 0; i < m_metadata.size(); i++) {
+            Element metadata = (Element) m_metadata.get(i);
+            meta.append(buildManifestMetadata(metadata, new StringBuffer()));
         }
         if (meta.length() != 0) {
             att.putValue("iPOJO-Components", meta.toString());
@@ -1013,10 +1018,10 @@
     private void parseXMLMetadata(File metadataFile) {
         try {
             InputStream stream = null;
-            URL url = metadataFile.toURL();
+            URL url = metadataFile.toURI().toURL();
             if (url == null) {
                 warn("Cannot find the metadata file : " + metadataFile.getAbsolutePath());
-                m_metadata = new Element[0];
+                m_metadata = new ArrayList/*Element*/();
             } else {
                 stream = url.openStream();
                 parseXMLMetadata(stream); // m_metadata is set by the method.
@@ -1074,7 +1079,7 @@
             warn("Neither component types, nor instances in the metadata");
         }
 
-        m_metadata = meta;
+        m_metadata.addAll(Arrays.asList(meta));
     }
 
     /**
@@ -1083,8 +1088,8 @@
      */
     private List getReferredPackages() {
         List referred = new ArrayList();
-        for (int i = 0; i < m_metadata.length; i++) {
-            Element[] elems = m_metadata[i].getElements();
+        for (int i = 0; i < m_metadata.size(); i++) {
+            Element[] elems = ((Element) m_metadata.get(i)).getElements();
             for (int j = 0; j < elems.length; j++) {
                 String att = elems[j].getAttribute("specification");
                 if (att != null) {