fixed regresion introduced by aspect annotation. Fixed aspect parsing, where callback lifecycle and composition parameters were not parsed

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@910046 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java
index 6eb7f35..a4a4da5 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java
@@ -79,8 +79,13 @@
     private String m_method;
     private String m_descriptor;
     private Set<String> m_methods = new HashSet<String>();
-    private List<Info> m_infos = new ArrayList<Info>();
+    private List<Info> m_infos = new ArrayList<Info>(); // Last elem is either Service or AspectService
     private MetaType m_metaType;
+    private String m_startMethod;
+    private String m_stopMethod;
+    private String m_initMethod;
+    private String m_destroyMethod;
+    private String m_compositionMethod;
 
     // Pattern used to parse the class parameter from the bind methods ("bind(Type)" or "bind(Map, Type)")
     private final static Pattern m_bindClassPattern = Pattern.compile("\\((Ljava/util/Map;)?L([^;]+);\\)V");
@@ -264,7 +269,6 @@
     public AnnotationCollector(Reporter reporter, MetaType metaType)
     {
         m_reporter = reporter;
-        m_infos.add(new Info(EntryTypes.Service));
         m_metaType = metaType;
     }
 
@@ -335,35 +339,39 @@
     public void annotation(Annotation annotation)
     {
         m_reporter.trace("Parsed annotation: %s", annotation);
-
-        if (annotation.getName().equals(A_INIT))
+        
+        if (annotation.getName().equals(A_SERVICE))
+        {
+            parseServiceAnnotation(annotation);
+        } 
+        else if (annotation.getName().equals(A_ASPECT_SERVICE))
+        {
+            parseAspectService(annotation);
+        }
+        else if (annotation.getName().equals(A_INIT))
         {
             checkMethod(m_voidMethodPattern);
-            m_infos.get(0).m_params.put(Params.init, m_method);
+            m_initMethod = m_method;
         }
         else if (annotation.getName().equals(A_START))
         {
             checkMethod(m_voidMethodPattern);
-            m_infos.get(0).m_params.put(Params.start, m_method);
+            m_startMethod = m_method;
         }
         else if (annotation.getName().equals(A_STOP))
         {
             checkMethod(m_voidMethodPattern);
-            m_infos.get(0).m_params.put(Params.stop, m_method);
+            m_stopMethod = m_method;
         }
         else if (annotation.getName().equals(A_DESTROY))
         {
             checkMethod(m_voidMethodPattern);
-            m_infos.get(0).m_params.put(Params.destroy, m_method);
+            m_destroyMethod = m_method;
         }
         else if (annotation.getName().equals(A_COMPOSITION))
         {
             checkMethod(m_methodCompoPattern);
-            m_infos.get(0).m_params.put(Params.composition, m_method);
-        }
-        else if (annotation.getName().equals(A_SERVICE))
-        {
-            parseServiceAnnotation(annotation);
+            m_compositionMethod = m_method;
         }
         else if (annotation.getName().equals(A_SERVICE_DEP))
         {
@@ -381,10 +389,6 @@
         {
             parsePropertiesMetaData(annotation);
         }
-        else if (annotation.getName().equals(A_ASPECT_SERVICE))
-        {
-            parseAspectService(annotation);
-        }
     }
 
     /**
@@ -393,7 +397,12 @@
      */
     private void parseServiceAnnotation(Annotation annotation)
     {
-        Info info = m_infos.get(0);
+        Info info = new Info(EntryTypes.Service);
+        m_infos.add(info);
+
+        // Register previously parsed Init/Start/Stop/Destroy/Composition annotations
+        addInitStartStopDestroyCompositionParams(info);
+        
         // impl attribute
         info.addParam(Params.impl, m_className);
 
@@ -410,6 +419,30 @@
         info.addParam(annotation, Params.factoryMethod, null);
     }
 
+    private void addInitStartStopDestroyCompositionParams(Info info)
+    {
+        if (m_initMethod != null) {
+            info.addParam(Params.init, m_initMethod);
+        }
+        
+        if (m_startMethod != null) {
+            info.addParam(Params.start, m_startMethod);
+        }
+        
+        if (m_stopMethod != null) {
+            info.addParam(Params.stop, m_stopMethod);
+        }
+        
+        if (m_destroyMethod != null) {
+            info.addParam(Params.destroy, m_destroyMethod);
+        }
+        
+        // Register Composition method
+        if (m_compositionMethod != null) {
+            info.addParam(Params.composition, m_compositionMethod);
+        }        
+    }
+
     /**
      * Parses a ServiceDependency or a TemporalServiceDependency Annotation.
      * @param annotation the ServiceDependency Annotation.
@@ -541,8 +574,11 @@
     private void parseAspectService(Annotation annotation)
     {
         Info info = new Info(EntryTypes.AspectService);
-        m_infos.set(0, info);
+        m_infos.add(info);
 
+        // Register previously parsed Init/Start/Stop/Destroy/Composition annotations
+        addInitStartStopDestroyCompositionParams(info);
+        
         // Parse Service interface.
         Object service = annotation.get(Params.service.toString());
         if (service == null) {
@@ -628,6 +664,34 @@
                 + m_descriptor);
         }
     }
+    
+    /**
+     * Checks if the class is annotated with some given annotations. Notice that the Service
+     * is always parsed at end of parsing, so, we have to check the last element of our m_infos
+     * List.
+     * @return true if one of the provided annotations has been found from the parsed class.
+     */
+    private void checkServiceDeclared(EntryTypes ... types) {
+        boolean ok = false;
+        if (m_infos.size() > 0)
+        {
+            for (EntryTypes type : types)
+            {
+                if (m_infos.get(m_infos.size() - 1).m_entry == type)
+                {
+                    ok = true;
+                    break;
+                }
+            }
+        }
+
+        if (!ok)
+        {
+            throw new IllegalStateException(
+                ": the class must be annotated with either one of the following types: "
+                    + Arrays.toString(types));
+        }
+    }
 
     /**
      * Get an annotation attribute, and return a default value if its not present.
@@ -645,28 +709,40 @@
 
     /**
      * Finishes up the class parsing. This method must be called once the parseClassFileWithCollector method has returned.
+     * @return true if some annotations have been parsed, false if not.
      */
-    public void finish()
+    public boolean finish()
     {
+        if (m_infos.size() == 0)
+        {
+            return false;
+        }
+
+        // We must have at least a Service or an AspectService annotation.
+        checkServiceDeclared(EntryTypes.Service, EntryTypes.AspectService);
+
         StringBuilder sb = new StringBuilder();
         sb.append("Parsed annotation for class ");
         sb.append(m_className);
-        for (Info info : m_infos)
+        for (int i = m_infos.size() - 1; i >= 0; i--)
         {
-            sb.append("\n\t").append(info.toString());
+            sb.append("\n\t").append(m_infos.get(i).toString());
         }
         m_reporter.warning(sb.toString());
+        return true;
     }
 
     /**
-     * Writes the generated component descriptor in the given print writer
+     * Writes the generated component descriptor in the given print writer.
+     * The first line must be the service (@Service or AspectService).
      * @param pw the writer where the component descriptor will be written.
      */
     public void writeTo(PrintWriter pw)
     {
-        for (Info info : m_infos)
+        // The last element our our m_infos list contains either the Service, or the AspectService descriptor.
+        for (int i = m_infos.size() - 1; i >= 0; i--)
         {
-            pw.println(info.toString());
+            pw.println(m_infos.get(i).toString());
         }
     }
 }
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/DescriptorGenerator.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/DescriptorGenerator.java
index 5fd5c17..055eb41 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/DescriptorGenerator.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/DescriptorGenerator.java
@@ -94,12 +94,14 @@
                 // Let's parse all annotations from that class !
                 AnnotationCollector reader = new AnnotationCollector(this, metaType);
                 c.parseClassFileWithCollector(reader);
-                reader.finish();
-                // And store the generated component descriptors in our resource list.
-                String name = c.getFQN();
-                Resource resource = createComponentResource(reader);
-                m_resources.put("OSGI-INF/dependencymanager/" + name, resource);
-                annotationsFound = true;
+                if (reader.finish()) 
+                {
+                    // And store the generated component descriptors in our resource list.
+                    String name = c.getFQN();
+                    Resource resource = createComponentResource(reader);
+                    m_resources.put("OSGI-INF/dependencymanager/" + name, resource);
+                    annotationsFound = true;
+                }
             }
 
             // If some Meta Types have been parsed, then creates the corresponding resource file.