FELIX-3332 : SCR annotations @Activate @Deactivate @Modified in outer classes also affect nested classes, annotations in nested classes are ignored 

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1440670 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/helper/ComponentContainerUtil.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/helper/ComponentContainerUtil.java
new file mode 100644
index 0000000..1ea2cda
--- /dev/null
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/helper/ComponentContainerUtil.java
@@ -0,0 +1,80 @@
+/*
+ * 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.scrplugin.helper;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public abstract class ComponentContainerUtil {
+
+    public static class ComponentContainerContainer {
+        public List<ComponentContainer> components;
+        public String className;
+    }
+
+    /**
+     * Split the list of components into separate lists depending
+     * on the configuration.
+     */
+    public static List<ComponentContainerContainer> split(final List<ComponentContainer> components,
+            final boolean generateSeparateDescriptors) {
+        final List<ComponentContainerContainer> result = new ArrayList<ComponentContainerContainer>();
+
+        if ( generateSeparateDescriptors ) {
+            while ( !components.isEmpty() ) {
+                // get the first component
+                final List<ComponentContainer> innerList = new ArrayList<ComponentContainer>();
+                final ComponentContainer component = components.remove(0);
+                innerList.add(component);
+                final int pos = component.getClassDescription().getDescribedClass().getName().indexOf('$');
+                final String baseClassName;
+                if ( pos == -1 ) {
+                    baseClassName = component.getClassDescription().getDescribedClass().getName();
+                } else {
+                    baseClassName = component.getClassDescription().getDescribedClass().getName().substring(0, pos);
+                }
+                final String baseClassPrefix = baseClassName + '$';
+
+                // check for inner classes
+                final Iterator<ComponentContainer> i = components.iterator();
+                while ( i.hasNext() ) {
+                    final ComponentContainer cc = i.next();
+                    if ( cc.getClassDescription().getDescribedClass().getName().startsWith(baseClassPrefix) ) {
+                        innerList.add(cc);
+                        i.remove();
+                    }
+                }
+
+                final ComponentContainerContainer ccc = new ComponentContainerContainer();
+                ccc.components = innerList;
+                ccc.className = baseClassName;
+                result.add(ccc);
+            }
+        } else {
+            if ( components.size() > 0 ) {
+                final ComponentContainerContainer ccc = new ComponentContainerContainer();
+                ccc.components = components;
+                result.add(ccc);
+            }
+        }
+
+        return result;
+    }
+}
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/xml/ComponentDescriptorIO.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/xml/ComponentDescriptorIO.java
index 2836783..215d4ee 100644
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/xml/ComponentDescriptorIO.java
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/xml/ComponentDescriptorIO.java
@@ -24,7 +24,6 @@
 import java.io.InputStream;
 import java.security.Provider.Service;
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
 import java.util.StringTokenizer;
 
@@ -48,6 +47,8 @@
 import org.apache.felix.scrplugin.description.ReferenceStrategy;
 import org.apache.felix.scrplugin.description.ServiceDescription;
 import org.apache.felix.scrplugin.helper.ComponentContainer;
+import org.apache.felix.scrplugin.helper.ComponentContainerUtil;
+import org.apache.felix.scrplugin.helper.ComponentContainerUtil.ComponentContainerContainer;
 import org.apache.felix.scrplugin.helper.DescriptionContainer;
 import org.apache.felix.scrplugin.helper.IssueLog;
 import org.apache.felix.scrplugin.helper.StringUtils;
@@ -734,6 +735,7 @@
      */
     public static List<String> generateDescriptorFiles(final DescriptionContainer module, final Options options, final Log logger)
             throws SCRDescriptorException, SCRDescriptorFailureException {
+        // get the list of all relevant containers
         final List<ComponentContainer> components = new ArrayList<ComponentContainer>();
         for(final ComponentContainer container : module.getComponents()) {
             if (!container.getComponentDescription().isCreateDs()) {
@@ -758,57 +760,33 @@
             }
             return null;
         }
+        if ( !options.isGenerateSeparateDescriptors() && descriptorFile == null ) {
+            throw new SCRDescriptorFailureException("Descriptor file name must not be empty.");
+        }
 
         // finally the descriptors have to be written ....
         descriptorDir.mkdirs(); // ensure parent dir
 
         final List<String> fileNames = new ArrayList<String>();
-        if ( options.isGenerateSeparateDescriptors() ) {
+        final List<ComponentContainerContainer> containers = ComponentContainerUtil.split(components, options.isGenerateSeparateDescriptors());
+        for(final ComponentContainerContainer ccc : containers) {
             final SpecVersion globalVersion = module.getOptions().getSpecVersion();
-            while ( !components.isEmpty() ) {
-                // get the first component
-                final List<ComponentContainer> innerList = new ArrayList<ComponentContainer>();
-                final ComponentContainer component = components.remove(0);
-                innerList.add(component);
-                final int pos = component.getClassDescription().getDescribedClass().getName().indexOf('$');
-                final String baseClassName;
-                if ( pos == -1 ) {
-                    baseClassName = component.getClassDescription().getDescribedClass().getName();
-                } else {
-                    baseClassName = component.getClassDescription().getDescribedClass().getName().substring(0, pos);
-                }
-                final String baseClassPrefix = baseClassName + '$';
 
-                // check for inner classes
-                final Iterator<ComponentContainer> i = components.iterator();
-                while ( i.hasNext() ) {
-                    final ComponentContainer cc = i.next();
-                    if ( cc.getClassDescription().getDescribedClass().getName().startsWith(baseClassPrefix) ) {
-                        innerList.add(cc);
-                        i.remove();
+            final File useFile;
+            if ( ccc.className == null ) {
+                useFile = descriptorFile;
+            } else {
+                SpecVersion sv = null;
+                for(final ComponentContainer cc : ccc.components ) {
+                    if ( sv == null || sv.ordinal() < cc.getComponentDescription().getSpecVersion().ordinal() ) {
+                        sv = cc.getComponentDescription().getSpecVersion();
                     }
                 }
-
-                module.getOptions().setSpecVersion(component.getComponentDescription().getSpecVersion());
-                final File file = new File(descriptorDir, baseClassName + ".xml");
-                try {
-                    ComponentDescriptorIO.generateXML(module, innerList, file, logger);
-                } catch (final IOException e) {
-                    throw new SCRDescriptorException("Unable to generate xml", file.toString(), e);
-                } catch (final TransformerException e) {
-                    throw new SCRDescriptorException("Unable to generate xml", file.toString(), e);
-                } catch (final SAXException e) {
-                    throw new SCRDescriptorException("Unable to generate xml", file.toString(), e);
-                }
-                fileNames.add(PARENT_NAME + '/' + file.getName());
-            }
-            module.getOptions().setSpecVersion(globalVersion);
-        } else {
-            if (descriptorFile == null) {
-                throw new SCRDescriptorFailureException("Descriptor file name must not be empty.");
+                module.getOptions().setSpecVersion(sv);
+                useFile = new File(descriptorDir, ccc.className + ".xml");
             }
             try {
-                ComponentDescriptorIO.generateXML(module, components, descriptorFile, logger);
+                ComponentDescriptorIO.generateXML(module, ccc.components, useFile, logger);
             } catch (final IOException e) {
                 throw new SCRDescriptorException("Unable to generate xml", descriptorFile.toString(), e);
             } catch (final TransformerException e) {
@@ -816,9 +794,11 @@
             } catch (final SAXException e) {
                 throw new SCRDescriptorException("Unable to generate xml", descriptorFile.toString(), e);
             }
-            fileNames.add(PARENT_NAME + '/' + descriptorFile.getName());
+            fileNames.add(PARENT_NAME + '/' + useFile.getName());
 
+            module.getOptions().setSpecVersion(globalVersion);
         }
+
         return fileNames;
     }
 }
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/xml/MetaTypeIO.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/xml/MetaTypeIO.java
index 7aa1dfb..853425d 100644
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/xml/MetaTypeIO.java
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/xml/MetaTypeIO.java
@@ -31,6 +31,8 @@
 import org.apache.felix.scrplugin.Options;
 import org.apache.felix.scrplugin.SCRDescriptorException;
 import org.apache.felix.scrplugin.helper.ComponentContainer;
+import org.apache.felix.scrplugin.helper.ComponentContainerUtil;
+import org.apache.felix.scrplugin.helper.ComponentContainerUtil.ComponentContainerContainer;
 import org.apache.felix.scrplugin.helper.DescriptionContainer;
 import org.apache.felix.scrplugin.helper.MetatypeAttributeDefinition;
 import org.apache.felix.scrplugin.helper.MetatypeContainer;
@@ -78,10 +80,11 @@
             final Options options,
             final Log logger)
                     throws SCRDescriptorException {
-        int metatypeCount = 0;
+        // create a list with relevant components
+        final List<ComponentContainer> components = new ArrayList<ComponentContainer>();
         for(final ComponentContainer component : module.getComponents()) {
             if ( component.getMetatypeContainer() != null ) {
-                metatypeCount++;
+                components.add(component);
             }
         }
         // write meta type info if there is a file name
@@ -91,53 +94,24 @@
 
             final File mtFile = new File(mtDir, options.getMetaTypeName());
 
-            if (metatypeCount > 0) {
+            if (components.size() > 0) {
                 mtDir.mkdirs();
 
                 final List<String> fileNames = new ArrayList<String>();
-                if ( options.isGenerateSeparateDescriptors() ) {
-                    // create a list with relevant components
-                    final List<ComponentContainer> components = new ArrayList<ComponentContainer>();
-                    for(final ComponentContainer component : module.getComponents() ) {
-                        if ( component.getMetatypeContainer() != null ) {
-                            components.add(component);
-                        }
+                final List<ComponentContainerContainer> containers = ComponentContainerUtil.split(components, options.isGenerateSeparateDescriptors());
+                for(final ComponentContainerContainer ccc : containers) {
+                    final File useFile;
+                    if ( ccc.className == null ) {
+                        useFile = mtFile;
+                    } else {
+                        useFile = new File(mtDir, ccc.className + ".xml");
                     }
+                    logger.info("Generating " + ccc.components.size() + " MetaType Descriptors in " + useFile);
+                    MetaTypeIO.write(module, ccc.components, useFile);
+                    fileNames.add(parentDir.getName() + '/' + mtDir.getName() + '/' + useFile.getName());
 
-                    while ( !components.isEmpty() ) {
-                        // get the first component
-                        final List<ComponentContainer> innerList = new ArrayList<ComponentContainer>();
-                        final ComponentContainer component = components.remove(0);
-                        innerList.add(component);
-                        final int pos = component.getClassDescription().getDescribedClass().getName().indexOf('$');
-                        final String baseClassName;
-                        if ( pos == -1 ) {
-                            baseClassName = component.getClassDescription().getDescribedClass().getName();
-                        } else {
-                            baseClassName = component.getClassDescription().getDescribedClass().getName().substring(0, pos);
-                        }
-                        final String baseClassPrefix = baseClassName + '$';
-
-                        // check for inner classes
-                        final Iterator<ComponentContainer> i = components.iterator();
-                        while ( i.hasNext() ) {
-                            final ComponentContainer cc = i.next();
-                            if ( cc.getClassDescription().getDescribedClass().getName().startsWith(baseClassPrefix) ) {
-                                innerList.add(cc);
-                                i.remove();
-                            }
-                        }
-
-                        final File file = new File(mtDir, baseClassName + ".xml");
-                        logger.info("Generating " + innerList.size() + " MetaType Descriptor in " + file);
-                        MetaTypeIO.write(module, innerList, file);
-                        fileNames.add(parentDir.getName() + '/' + mtDir.getName() + '/' + file.getName());
-                    }
-                } else {
-                    logger.info("Generating " + metatypeCount + " MetaType Descriptors in " + mtFile);
-                    MetaTypeIO.write(module, module.getComponents(), mtFile);
-                    fileNames.add(parentDir.getName() + '/' + mtDir.getName() + '/' + mtFile.getName());
                 }
+
                 return fileNames;
             }
             if (mtFile.exists()) {
@@ -145,7 +119,7 @@
             }
 
         } else {
-            if ( metatypeCount > 0 ) {
+            if (components.size() > 0) {
                 logger.info("Meta type file name is not set: meta type info is not written.");
             }
         }