FELIX-3641 :  Option to generate separate descriptor files 

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1379319 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/Options.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/Options.java
index 03acc1e..a57f858 100644
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/Options.java
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/Options.java
@@ -49,6 +49,9 @@
     /** The name of the metatype file. */
     private String metaTypeName = "metatype.xml";
 
+    /** Flag for generating separate descriptor files. */
+    private boolean generateSeparateDescriptors = false;
+
     /**
      * @see #setGenerateAccessors(boolean)
      * @return Whether accessor methods should be generated.
@@ -187,4 +190,19 @@
     public void setMetaTypeName(final String metaTypeName) {
         this.metaTypeName = metaTypeName;
     }
+
+    /**
+     * Should separate descriptor files be generated?
+     */
+    public boolean isGenerateSeparateDescriptors() {
+        return generateSeparateDescriptors;
+    }
+
+    /**
+     * Set whether separate descriptor files should be generated.
+     * @param generateSeparateDescriptors
+     */
+    public void setGenerateSeparateDescriptors(boolean generateSeparateDescriptors) {
+        this.generateSeparateDescriptors = generateSeparateDescriptors;
+    }
 }
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/SCRDescriptorGenerator.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/SCRDescriptorGenerator.java
index 4573735..11a2a26 100644
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/SCRDescriptorGenerator.java
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/SCRDescriptorGenerator.java
@@ -133,6 +133,7 @@
         this.logger.debug("..using metatype name: " + this.options.getMetaTypeName());
         this.logger.debug("..strict mode: " + this.options.isStrictMode());
         this.logger.debug("..generating accessors: " + this.options.isGenerateAccessors());
+        this.logger.debug("..generating separate descs: " + this.options.isGenerateSeparateDescriptors());
 
         // check speck version configuration
         SpecVersion specVersion = options.getSpecVersion();
@@ -295,30 +296,9 @@
         }
 
         // check descriptor file
-        final String descriptorPath = "OSGI-INF" + File.separator + this.options.getSCRName();
-        final File descriptorFile = StringUtils.isEmpty(this.options.getSCRName()) ? null : new File(this.options.getOutputDirectory(), descriptorPath);
-
-        // terminate if there is nothing else to write
-        if (module.getComponents().isEmpty()) {
-            this.logger.debug("No Service Component Descriptors found in project.");
-            // remove file if it exists
-            if (descriptorFile != null && descriptorFile.exists()) {
-                this.logger.debug("Removing obsolete service descriptor " + descriptorFile);
-                descriptorFile.delete();
-            }
-        } else {
-            if (descriptorFile == null) {
-                throw new SCRDescriptorFailureException("Descriptor file name must not be empty.");
-            }
-
-            // finally the descriptors have to be written ....
-            descriptorFile.getParentFile().mkdirs(); // ensure parent dir
-
-            this.logger.info("Writing " + module.getComponents().size() + " Service Component Descriptors to "
-                            + descriptorFile);
-
-            ComponentDescriptorIO.write(module, descriptorFile);
-            result.setScrFiles(Collections.singletonList(descriptorPath.replace(File.separatorChar, '/')));
+        final List<String> descriptorFiles = ComponentDescriptorIO.generateDescriptorFiles(module, this.options, logger);
+        if ( descriptorFiles != null ) {
+            result.setScrFiles(descriptorFiles);
         }
 
         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 57b17e6..c3e3c3c 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
@@ -20,16 +20,19 @@
 
 import java.awt.Component;
 import java.io.File;
-import java.io.IOException;
 import java.io.InputStream;
 import java.security.Provider.Service;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.StringTokenizer;
 
 import javax.xml.transform.TransformerException;
 
+import org.apache.felix.scrplugin.Log;
+import org.apache.felix.scrplugin.Options;
 import org.apache.felix.scrplugin.SCRDescriptorException;
+import org.apache.felix.scrplugin.SCRDescriptorFailureException;
 import org.apache.felix.scrplugin.SpecVersion;
 import org.apache.felix.scrplugin.description.ClassDescription;
 import org.apache.felix.scrplugin.description.ComponentConfigurationPolicy;
@@ -46,6 +49,7 @@
 import org.apache.felix.scrplugin.helper.ComponentContainer;
 import org.apache.felix.scrplugin.helper.DescriptionContainer;
 import org.apache.felix.scrplugin.helper.IssueLog;
+import org.apache.felix.scrplugin.helper.StringUtils;
 import org.xml.sax.Attributes;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
@@ -169,25 +173,6 @@
     }
 
     /**
-     * Write the component descriptors to the file.
-     *
-     * @param module
-     * @param file
-     * @throws SCRDescriptorException
-     */
-    public static void write(final DescriptionContainer module, final File file) throws SCRDescriptorException {
-        try {
-            generateXML(module, IOUtils.getSerializer(file));
-        } catch (final TransformerException e) {
-            throw new SCRDescriptorException("Unable to write xml", file.toString(), e);
-        } catch (final SAXException e) {
-            throw new SCRDescriptorException("Unable to generate xml", file.toString(), e);
-        } catch (final IOException e) {
-            throw new SCRDescriptorException("Unable to write xml", file.toString(), e);
-        }
-    }
-
-    /**
      * Generate the xml top level element and start streaming
      * the components.
      *
@@ -196,7 +181,12 @@
      * @throws SAXException
      */
     protected static void generateXML(final DescriptionContainer module,
-                    final ContentHandler contentHandler) throws SAXException {
+                    final List<ComponentContainer> components,
+                    final File descriptorFile,
+                    final Log logger) throws SAXException {
+        logger.info("Writing " + components.size() + " Service Component Descriptors to "
+                        + descriptorFile);
+        final ContentHandler contentHandler = IOUtils.getSerializer(descriptorFile);
         // detect namespace to use
         final String namespace = module.getOptions().getSpecVersion().getNamespaceUrl();
 
@@ -207,7 +197,7 @@
         contentHandler.startElement("", ComponentDescriptorIO.COMPONENTS, ComponentDescriptorIO.COMPONENTS, new AttributesImpl());
         IOUtils.newline(contentHandler);
 
-        for (final ComponentContainer component : module.getComponents()) {
+        for (final ComponentContainer component : components) {
             generateXML(namespace, module, component, contentHandler);
         }
 
@@ -711,4 +701,55 @@
             }
         }
     }
+
+    private static final String PARENT_NAME = "OSGI-INF";
+
+    /**
+     * Generate descriptor file(s)
+     */
+    public static List<String> generateDescriptorFiles(final DescriptionContainer module, final Options options, final Log logger)
+    throws SCRDescriptorException, SCRDescriptorFailureException {
+        // check descriptor file
+        final File descriptorDir = new File(options.getOutputDirectory(), PARENT_NAME);
+        final File descriptorFile = StringUtils.isEmpty(options.getSCRName()) ? null : new File(descriptorDir, options.getSCRName());
+
+        // terminate if there is nothing else to write
+        if (module.getComponents().isEmpty()) {
+            logger.debug("No Service Component Descriptors found in project.");
+            // remove file if it exists
+            if (descriptorFile != null && descriptorFile.exists()) {
+                logger.debug("Removing obsolete service descriptor " + descriptorFile);
+                descriptorFile.delete();
+            }
+            return null;
+        }
+
+        // finally the descriptors have to be written ....
+        descriptorDir.mkdirs(); // ensure parent dir
+
+        final List<String> fileNames = new ArrayList<String>();
+        if ( options.isGenerateSeparateDescriptors() ) {
+            for(final ComponentContainer component : module.getComponents() ) {
+                final File file = new File(descriptorDir, component.getClassDescription().getDescribedClass().getName() + ".xml");
+                try {
+                    ComponentDescriptorIO.generateXML(module, Collections.singletonList(component), file, logger);
+                } catch (final SAXException e) {
+                    throw new SCRDescriptorException("Unable to generate xml", file.toString(), e);
+                }
+                fileNames.add(PARENT_NAME + '/' + file.getName());
+            }
+        } else {
+            if (descriptorFile == null) {
+                throw new SCRDescriptorFailureException("Descriptor file name must not be empty.");
+            }
+            try {
+                ComponentDescriptorIO.generateXML(module, module.getComponents(), descriptorFile, logger);
+            } catch (final SAXException e) {
+                throw new SCRDescriptorException("Unable to generate xml", descriptorFile.toString(), e);
+            }
+            fileNames.add(PARENT_NAME + '/' + descriptorFile.getName());
+
+        }
+        return fileNames;
+    }
 }
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/xml/IOUtils.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/xml/IOUtils.java
index 6f48889..18aa50f 100644
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/xml/IOUtils.java
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/xml/IOUtils.java
@@ -18,15 +18,31 @@
  */
 package org.apache.felix.scrplugin.xml;
 
-import java.io.*;
-import java.util.*;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
 
-import javax.xml.transform.*;
-import javax.xml.transform.sax.*;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
 import javax.xml.transform.stream.StreamResult;
 import javax.xml.transform.stream.StreamSource;
 
-import org.xml.sax.*;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
 import org.xml.sax.helpers.AttributesImpl;
 
 /**
@@ -54,30 +70,33 @@
         transformer.transform( new StreamSource( file ), new SAXResult( handler ) );
     }
 
-    public static ContentHandler getSerializer(File file)
-    throws IOException, TransformerException {
-        final FileWriter writer = new FileWriter(file);
-
-        final TransformerHandler transformerHandler = FACTORY.newTransformerHandler();
-        final Transformer transformer = transformerHandler.getTransformer();
-
-        final Properties format = new Properties();
-        format.put(OutputKeys.METHOD, "xml");
-        format.put(OutputKeys.OMIT_XML_DECLARATION, "no");
-        format.put(OutputKeys.ENCODING, "UTF-8");
-        format.put(OutputKeys.INDENT, "yes");
-        transformer.setOutputProperties(format);
-
-        transformerHandler.setResult(new StreamResult(writer));
-
+    public static ContentHandler getSerializer(final File file)
+    throws SAXException {
         try {
+            final FileWriter writer = new FileWriter(file);
+
+            final TransformerHandler transformerHandler = FACTORY.newTransformerHandler();
+            final Transformer transformer = transformerHandler.getTransformer();
+
+            final Properties format = new Properties();
+            format.put(OutputKeys.METHOD, "xml");
+            format.put(OutputKeys.OMIT_XML_DECLARATION, "no");
+            format.put(OutputKeys.ENCODING, "UTF-8");
+            format.put(OutputKeys.INDENT, "yes");
+            transformer.setOutputProperties(format);
+
+            transformerHandler.setResult(new StreamResult(writer));
+
             if ( needsNamespacesAsAttributes(format) ) {
                 return new NamespaceAsAttributes(transformerHandler);
             }
-        } catch (SAXException se) {
-            throw new TransformerException("Unable to detect of namespace support for sax works properly.", se);
+
+            return transformerHandler;
+        } catch (final IOException se) {
+            throw new SAXException("Unable to detect if namespace support for sax works properly.", se);
+        } catch (final TransformerException se) {
+            throw new SAXException("Unable to detect if namespace support for sax works properly.", se);
         }
-        return transformerHandler;
     }
 
     /**
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 4810e25..84b2ee2 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
@@ -19,12 +19,9 @@
 package org.apache.felix.scrplugin.xml;
 
 import java.io.File;
-import java.io.IOException;
 import java.util.Iterator;
 import java.util.Map;
 
-import javax.xml.transform.TransformerException;
-
 import org.apache.felix.scrplugin.SCRDescriptorException;
 import org.apache.felix.scrplugin.om.metatype.AttributeDefinition;
 import org.apache.felix.scrplugin.om.metatype.Designate;
@@ -68,16 +65,12 @@
     protected static final String OPTION_ELEMENT = "Option";
     protected static final String OPTION_ELEMENT_QNAME = OPTION_ELEMENT;
 
-    public static void write(MetaData metaData, File file)
+    public static void write(final MetaData metaData, final File file)
     throws SCRDescriptorException {
         try {
             generateXML(metaData, IOUtils.getSerializer(file));
-        } catch (TransformerException e) {
-            throw new SCRDescriptorException("Unable to write xml", file.toString(), e);
-        } catch (SAXException e) {
+        } catch (final SAXException e) {
             throw new SCRDescriptorException("Unable to generate xml", file.toString(), e);
-        } catch (IOException e) {
-            throw new SCRDescriptorException("Unable to write xml", file.toString(), e);
         }
     }