[FELIX-3863] - Generate DependencyManager Annotation MetaData In Project Folder.


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1437070 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/annotation/doc/changelog.txt b/dependencymanager/annotation/doc/changelog.txt
index 0ea1c46..69e4653 100644
--- a/dependencymanager/annotation/doc/changelog.txt
+++ b/dependencymanager/annotation/doc/changelog.txt
@@ -10,6 +10,7 @@
     * [FELIX-2956] - json should be embedded in the annotation scanner plugin
     * [FELIX-2966] - Annotations should automatically generate Import-Service/Export-Service headers
     * [FELIX-2965] - Annotations should allow to enable or disable auto-configuration mode.
+    * [FELIX-3863] - Generate DependencyManager Annotation MetaData In Project Folder
 
 Initial Release 3.0.0
 ---------------------
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/AnnotationPlugin.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/AnnotationPlugin.java
index 35c9077..e8de8ee 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/AnnotationPlugin.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/AnnotationPlugin.java
@@ -48,11 +48,11 @@
     /**
      * This plugin is called after analysis of the JAR but before manifest
      * generation. When some DM annotations are found, the plugin will add the corresponding 
-     * DM component descriptors under OSGI-INF/ directory. It will also set the  
+     * DM component descriptors under META-INF/ directory. It will also set the  
      * "DependencyManager-Component" manifest header (which references the descriptor paths).
      * 
      * @param analyzer the object that is used to retrieve classes containing DM annotations.
-     * @return true if the classpace has been modified so that the bundle classpath must be reanalyzed
+     * @return true if the classpath has been modified so that the bundle classpath must be reanalyzed
      * @throws Exception on any errors.
      */
     public boolean analyzeJar(Analyzer analyzer) throws Exception
@@ -90,7 +90,7 @@
                     analyzer.getJar().putResource(entry.getKey(), entry.getValue());
                 }
 
-                // Inser the metatype resource, if any.
+                // Insert the metatype resource, if any.
                 Resource metaType = generator.getMetaTypeResource();
                 if (metaType != null)
                 {
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/mvn/AnnotationMojo.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/mvn/AnnotationMojo.java
index 7672879..ad9f4c7 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/mvn/AnnotationMojo.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/mvn/AnnotationMojo.java
@@ -18,8 +18,12 @@
  */
 package org.apache.felix.dm.annotation.plugin.mvn;
 
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
 import java.io.File;
+import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.util.Map;
 import java.util.Set;
 
@@ -36,7 +40,7 @@
 /**
  * The <code>AnnotationMojo</code>
  * generates a Dependency Manager component descriptor file based on annotations found from java classes.
- *
+ * 
  * @goal scan
  * @phase package
  * @description Build DependencyManager component descriptors from class annotations.
@@ -47,7 +51,7 @@
 {
     /**
      * The Maven project.
-     *
+     * 
      * @parameter expression="${project}"
      * @required
      * @readonly
@@ -56,7 +60,7 @@
 
     /**
      * The target extension
-     *
+     * 
      * @parameter default-value="jar"
      * @required
      */
@@ -64,19 +68,35 @@
 
     /**
      * If set, configures the log level.
-     *
+     * 
      * @parameter alias="log"
      */
     private String m_log;
 
     /**
      * If set, configures if we must auto generate Import-Service/Export-Service headers.
-     *
+     * 
      * @parameter alias="build-import-export-service" default-value="true"
      */
     private boolean m_buildImportExportService;
 
     /**
+     * The maven project bas directory, used when generating metadata in maven project directory.
+     * 
+     * @parameter expression="${project.basedir}"
+     * @required
+     * @readonly
+     */
+    private File m_projectBaseDir;
+    
+    /**
+     * If set, configures the output directory where generated descriptor files are generated.
+     * 
+     * @parameter alias="generated-output-dir"
+     */
+    private String m_generatedOutputDir;
+
+    /**
      * "Import-Service" osgi header
      */
     private static final String IMPORT_SERVICE = "Import-Service";
@@ -87,7 +107,8 @@
     private static final String EXPORT_SERVICE = "Export-Service";
 
     /**
-     * Executes this mojo. We'll use the bnd library in order to scan classes from our target bundle.
+     * Executes this mojo. We'll use the bnd library in order to scan classes
+     * from our target bundle.
      */
     public void execute() throws MojoExecutionException
     {
@@ -111,29 +132,34 @@
             // Start scanning
             if (generator.execute())
             {
-                // Some annotations have been parsed. 
-                // Add the list of generated component descriptors in our special header.
+                // Some annotations have been parsed.
+                // Add the list of generated component descriptors in our
+                // special header.
                 jar = analyzer.getJar();
-                jar.getManifest().getMainAttributes().putValue("DependencyManager-Component",
-                                                               generator.getDescriptorPaths());
+                jar.getManifest().getMainAttributes()
+                    .putValue( "DependencyManager-Component", generator.getDescriptorPaths() );
 
-                // Add generated descriptors into the target bundle (we'll use a temp file).
+                // Add generated descriptors into the target bundle (we'll use a
+                // temp file).
                 Map<String, Resource> resources = generator.getDescriptors();
                 for (Map.Entry<String, Resource> entry : resources.entrySet())
                 {
+                    addResource(entry.getKey(), entry.getValue().openInputStream());
                     jar.putResource(entry.getKey(), entry.getValue());
                 }
 
                 Resource metaType = generator.getMetaTypeResource();
                 if (metaType != null)
                 {
+                    addResource("OSGI-INF/metatype/metatype.xml", metaType.openInputStream());
                     jar.putResource("OSGI-INF/metatype/metatype.xml", metaType);
                 }
 
                 // Possibly set the Import-Service/Export-Service header
                 if (m_buildImportExportService)
                 {
-                    // Don't override Import-Service header, if it is found from the bnd directives.
+                    // Don't override Import-Service header, if it is found from
+                    // the bnd directives.
                     if (jar.getManifest().getMainAttributes().getValue(IMPORT_SERVICE) == null)
                     {
                         buildImportExportService(jar, IMPORT_SERVICE, generator.getImportService());
@@ -170,6 +196,29 @@
         }
     }
 
+    /**
+     * Adds a resource file into the project base directory
+     * @param key
+     * @param in
+     * @throws IOException
+     */
+    private void addResource(String key, InputStream in) throws IOException
+    {
+        if (m_generatedOutputDir != null) {
+            File descriptorFile = new File( m_projectBaseDir + File.separator + m_generatedOutputDir, key );
+            descriptorFile.getParentFile().mkdirs();
+            BufferedInputStream bin = new BufferedInputStream( in );
+            BufferedOutputStream out = new BufferedOutputStream( new FileOutputStream( descriptorFile ) );
+            int b;
+            while ( ( b = bin.read() ) != -1 )
+            {
+                out.write( b );
+            }
+            out.close();
+            bin.close();
+        }
+    }
+
     private void buildImportExportService(Jar jar, String header, Set<String> services) throws IOException
     {
         getLog().info("building " + header + " header with the following services: " + services);
@@ -189,6 +238,7 @@
 
     /**
      * Returns the target name of this maven project.
+     * 
      * @return the target name of this maven project.
      */
     private File getBundleName()
@@ -200,6 +250,7 @@
 
     /**
      * Copy the generated jar into our target bundle.
+     * 
      * @param jar the jar with the generated component descriptors
      * @param target our target bundle
      * @throws MojoExecutionException on any errors