git-svn-id: https://svn.apache.org/repos/asf/incubator/felix/trunk@239335 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/sandbox/tbennett/maven-archiver/pom.xml b/sandbox/tbennett/maven-archiver/pom.xml
new file mode 100644
index 0000000..300d915
--- /dev/null
+++ b/sandbox/tbennett/maven-archiver/pom.xml
@@ -0,0 +1,29 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <artifactId>maven</artifactId>
+    <groupId>org.apache.maven</groupId>
+    <version>2.0-alpha-3</version>
+  </parent>
+  <artifactId>maven-archiver</artifactId>
+  <name>Maven Archiver</name>
+  <version>2.0-alpha-3</version>
+  <dependencies>
+    <dependency>
+      <groupId>plexus</groupId>
+      <artifactId>plexus-archiver</artifactId>
+      <version>1.0-alpha-1</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-artifact</artifactId>
+      <version>2.0-alpha-3</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-project</artifactId>
+      <version>2.0-alpha-3</version>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/sandbox/tbennett/maven-archiver/src/main/java/org/apache/maven/archiver/ManifestConfiguration.java b/sandbox/tbennett/maven-archiver/src/main/java/org/apache/maven/archiver/ManifestConfiguration.java
new file mode 100644
index 0000000..7ff960c
--- /dev/null
+++ b/sandbox/tbennett/maven-archiver/src/main/java/org/apache/maven/archiver/ManifestConfiguration.java
@@ -0,0 +1,78 @@
+package org.apache.maven.archiver;
+
+/*
+ * Copyright 2001-2005 The Apache Software Foundation.
+ *
+ * Licensed 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.
+ */
+
+/**
+ * Capture common manifest configuration.
+ *
+ * @author <a href="mailto:brett@apache.org">Brett Porter</a>
+ * @version $Id: ManifestConfiguration.java 209060 2005-07-04 11:59:42Z evenisse $
+ * @todo is this general enough to be in Plexus Archiver?
+ */
+public class ManifestConfiguration
+{
+    private String mainClass;
+
+    private String packageName;
+
+    /**
+     * @todo boolean instead
+     */
+    private String addClasspath;
+
+    /**
+     * @todo boolean instead
+     */
+    private String addExtensions;
+
+    /**
+     * This gets prefixed to all classpath entries.
+     */
+    private String classpathPrefix = "";
+
+    public String getMainClass()
+    {
+        return mainClass;
+    }
+
+    public boolean isAddClasspath()
+    {
+        return addClasspath != null ? Boolean.valueOf( addClasspath ).booleanValue() : false;
+    }
+
+    public boolean isAddExtensions()
+    {
+        return addExtensions != null ? Boolean.valueOf( addExtensions ).booleanValue() : false;
+    }
+
+    public String getPackageName()
+    {
+        return packageName;
+    }
+
+    public String getClasspathPrefix()
+    {
+        String cpp = classpathPrefix.replaceAll( "\\\\", "/" );
+
+        if ( cpp.length() != 0 && !cpp.endsWith("/") )
+        {
+            cpp += "/";
+        }
+        
+        return cpp;
+    }
+}
diff --git a/sandbox/tbennett/maven-archiver/src/main/java/org/apache/maven/archiver/MavenArchiveConfiguration.java b/sandbox/tbennett/maven-archiver/src/main/java/org/apache/maven/archiver/MavenArchiveConfiguration.java
new file mode 100644
index 0000000..ec14472
--- /dev/null
+++ b/sandbox/tbennett/maven-archiver/src/main/java/org/apache/maven/archiver/MavenArchiveConfiguration.java
@@ -0,0 +1,101 @@
+package org.apache.maven.archiver;
+
+/*
+ * Copyright 2001-2005 The Apache Software Foundation.
+ *
+ * Licensed 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.
+ */
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Capture common archive configuration.
+ *
+ * @author <a href="mailto:brett@apache.org">Brett Porter</a>
+ * @version $Id: MavenArchiveConfiguration.java 225504 2005-07-27 12:48:52Z brett $
+ * @todo is this general enough to be in Plexus Archiver?
+ */
+public class MavenArchiveConfiguration
+{
+    private boolean compress = true;
+
+    private boolean index;
+
+    private File manifestFile;
+
+    private ManifestConfiguration manifest;
+
+	private Map manifestEntries = new HashMap();
+
+    public boolean isCompress()
+    {
+        return compress;
+    }
+
+    public boolean isIndex()
+    {
+        return index;
+    }
+
+    public File getManifestFile()
+    {
+        return manifestFile;
+    }
+
+    public ManifestConfiguration getManifest()
+    {
+        if ( manifest == null )
+        {
+            manifest = new ManifestConfiguration();
+        }
+        return manifest;
+    }
+
+    public void setCompress( boolean compress )
+    {
+        this.compress = compress;
+    }
+
+    public void setIndex( boolean index )
+    {
+        this.index = index;
+    }
+
+    public void setManifestFile( File manifestFile )
+    {
+        this.manifestFile = manifestFile;
+    }
+
+    public void setManifest( ManifestConfiguration manifest )
+    {
+        this.manifest = manifest;
+    }
+
+	public void addManifestEntry(Object key, Object value) {
+		manifestEntries.put(key, value);
+	}
+
+	public void addManifestEntries(Map map) {
+		manifestEntries.putAll(map);
+	}
+
+	public boolean isManifestEntriesEmpty() {
+		return manifestEntries.isEmpty();
+	}
+
+	public Map getManifestEntries() {
+		return manifestEntries;
+	}
+}
diff --git a/sandbox/tbennett/maven-archiver/src/main/java/org/apache/maven/archiver/MavenArchiver.java b/sandbox/tbennett/maven-archiver/src/main/java/org/apache/maven/archiver/MavenArchiver.java
new file mode 100644
index 0000000..16192e3
--- /dev/null
+++ b/sandbox/tbennett/maven-archiver/src/main/java/org/apache/maven/archiver/MavenArchiver.java
@@ -0,0 +1,317 @@
+package org.apache.maven.archiver;
+
+/*
+ * Copyright 2001-2005 The Apache Software Foundation.
+ *
+ * Licensed 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.
+ */
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.DependencyResolutionRequiredException;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.archiver.ArchiverException;
+import org.codehaus.plexus.archiver.jar.JarArchiver;
+import org.codehaus.plexus.archiver.jar.Manifest;
+import org.codehaus.plexus.archiver.jar.ManifestException;
+import org.codehaus.plexus.util.IOUtil;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+/**
+ * @author <a href="evenisse@apache.org">Emmanuel Venisse</a>
+ * @version $Revision: 225504 $ $Date: 2005-07-27 07:48:52 -0500 (Wed, 27 Jul 2005) $
+ */
+public class MavenArchiver
+{
+    private JarArchiver archiver = new JarArchiver();
+
+    private File archiveFile;
+
+    /**
+     * Return a pre-configured manifest
+     *
+     * @todo Add user attributes list and user groups list
+     */
+    public Manifest getManifest( MavenProject project, ManifestConfiguration config )
+        throws ManifestException, DependencyResolutionRequiredException
+    {
+        // Added basic entries
+        Manifest m = new Manifest();
+        Manifest.Attribute buildAttr = new Manifest.Attribute( "Built-By", System.getProperty( "user.name" ) );
+        m.addConfiguredAttribute( buildAttr );
+        Manifest.Attribute createdAttr = new Manifest.Attribute( "Created-By", "Apache Maven" );
+        m.addConfiguredAttribute( createdAttr );
+
+        if ( config.getPackageName() != null )
+        {
+            Manifest.Attribute packageAttr = new Manifest.Attribute( "Package", config.getPackageName() );
+            m.addConfiguredAttribute( packageAttr );
+        }
+
+        Manifest.Attribute buildJdkAttr = new Manifest.Attribute( "Build-Jdk", System.getProperty( "java.version" ) );
+        m.addConfiguredAttribute( buildJdkAttr );
+
+        if ( config.isAddClasspath() )
+        {
+            StringBuffer classpath = new StringBuffer();
+            List artifacts = project.getRuntimeClasspathElements();
+            String classpathPrefix = config.getClasspathPrefix();
+
+            for ( Iterator iter = artifacts.iterator(); iter.hasNext(); )
+            {
+                File f = new File( (String) iter.next() );
+                if ( f.isFile() )
+                {
+                    if ( classpath.length() > 0 )
+                    {
+                        classpath.append( " " );
+                    }
+
+                    classpath.append( classpathPrefix );
+                    classpath.append( f.getName() );
+                }
+            }
+
+            if ( classpath.length() > 0 )
+            {
+                Manifest.Attribute classpathAttr = new Manifest.Attribute( "Class-Path", classpath.toString() );
+                m.addConfiguredAttribute( classpathAttr );
+            }
+        }
+
+        // Added supplementary entries
+        Manifest.Attribute extensionNameAttr = new Manifest.Attribute( "Extension-Name", project.getArtifactId() );
+        m.addConfiguredAttribute( extensionNameAttr );
+
+        if ( project.getDescription() != null )
+        {
+            Manifest.Attribute specificationTitleAttr = new Manifest.Attribute( "Specification-Title",
+                                                                                project.getDescription() );
+            m.addConfiguredAttribute( specificationTitleAttr );
+        }
+
+        if ( project.getOrganization() != null )
+        {
+            Manifest.Attribute specificationVendor = new Manifest.Attribute( "Specification-Vendor",
+                                                                             project.getOrganization().getName() );
+            m.addConfiguredAttribute( specificationVendor );
+            Manifest.Attribute implementationVendorAttr = new Manifest.Attribute( "Implementation-Vendor",
+                                                                                  project.getOrganization().getName() );
+            m.addConfiguredAttribute( implementationVendorAttr );
+        }
+
+        Manifest.Attribute implementationTitleAttr = new Manifest.Attribute( "Implementation-Title",
+                                                                             project.getArtifactId() );
+        m.addConfiguredAttribute( implementationTitleAttr );
+        Manifest.Attribute implementationVersionAttr = new Manifest.Attribute( "Implementation-Version",
+                                                                               project.getVersion() );
+        m.addConfiguredAttribute( implementationVersionAttr );
+
+        String mainClass = config.getMainClass();
+        if ( mainClass != null && !"".equals( mainClass ) )
+        {
+            Manifest.Attribute mainClassAttr = new Manifest.Attribute( "Main-Class", mainClass );
+            m.addConfiguredAttribute( mainClassAttr );
+        }
+
+        // Added extensions
+        if ( config.isAddExtensions() )
+        {
+            StringBuffer extensionsList = new StringBuffer();
+            Set artifacts = project.getArtifacts();
+
+            for ( Iterator iter = artifacts.iterator(); iter.hasNext(); )
+            {
+                Artifact artifact = (Artifact) iter.next();
+                // TODO: type of ejb should be added too?
+                if ( "jar".equals( artifact.getType() ) )
+                {
+                    if ( extensionsList.length() > 0 )
+                    {
+                        extensionsList.append( " " );
+                    }
+                    extensionsList.append( artifact.getArtifactId() );
+                }
+            }
+
+            if ( extensionsList.length() > 0 )
+            {
+                Manifest.Attribute extensionsListAttr = new Manifest.Attribute( "Extension-List",
+                                                                                extensionsList.toString() );
+                m.addConfiguredAttribute( extensionsListAttr );
+            }
+
+            for ( Iterator iter = artifacts.iterator(); iter.hasNext(); )
+            {
+                Artifact artifact = (Artifact) iter.next();
+                if ( "jar".equals( artifact.getType() ) )
+                {
+                    Manifest.Attribute archExtNameAttr = new Manifest.Attribute(
+                        artifact.getArtifactId() + "-Extension-Name", artifact.getArtifactId() );
+                    m.addConfiguredAttribute( archExtNameAttr );
+                    String name = artifact.getArtifactId() + "-Implementation-Version";
+                    Manifest.Attribute archImplVersionAttr = new Manifest.Attribute( name, artifact.getVersion() );
+                    m.addConfiguredAttribute( archImplVersionAttr );
+
+                    if ( artifact.getRepository() != null )
+                    {
+                        // TODO: is this correct
+                        name = artifact.getArtifactId() + "-Implementation-URL";
+                        String url = artifact.getRepository().getUrl() + "/" + artifact.toString();
+                        Manifest.Attribute archImplUrlAttr = new Manifest.Attribute( name, url );
+                        m.addConfiguredAttribute( archImplUrlAttr );
+                    }
+                }
+            }
+        }
+
+        return m;
+    }
+
+    public JarArchiver getArchiver()
+    {
+        return archiver;
+    }
+
+    public void setArchiver( JarArchiver archiver )
+    {
+        this.archiver = archiver;
+    }
+
+    public void setOutputFile( File outputFile )
+    {
+        archiveFile = outputFile;
+    }
+
+    public void createArchive( MavenProject project, MavenArchiveConfiguration archiveConfiguration )
+        throws ArchiverException, ManifestException, IOException, DependencyResolutionRequiredException
+    {
+        // ----------------------------------------------------------------------
+        // We want to add the metadata for the project to the JAR in two forms:
+        //
+        // The first form is that of the POM itself. Applications that wish to
+        // access the POM for an artifact using maven tools they can.
+        //
+        // The second form is that of a properties file containing the basic
+        // top-level POM elements so that applications that wish to access
+        // POM information without the use of maven tools can do so.
+        // ----------------------------------------------------------------------
+
+        String groupId = project.getGroupId();
+
+        String artifactId = project.getArtifactId();
+
+        File exportReadyPom = writeExportReadyPom( project );
+
+        archiver.addFile( exportReadyPom, "META-INF/maven/" + groupId + "/" + artifactId + "/pom.xml" );
+
+        // ----------------------------------------------------------------------
+        // Create pom.properties file
+        // ----------------------------------------------------------------------
+
+        Properties p = new Properties();
+
+        p.setProperty( "groupId", project.getGroupId() );
+
+        p.setProperty( "artifactId", project.getArtifactId() );
+
+        p.setProperty( "version", project.getVersion() );
+
+        File pomPropertiesFile = new File( project.getFile().getParentFile(), "pom.properties" );
+
+        OutputStream os = new FileOutputStream( pomPropertiesFile );
+
+        p.store( os, "Generated by Maven" );
+
+        os.close(); // stream is flushed but not closed by Properties.store()
+
+        archiver.addFile( pomPropertiesFile, "META-INF/maven/" + groupId + "/" + artifactId + "/pom.properties" );
+
+        // ----------------------------------------------------------------------
+        // Create the manifest
+        // ----------------------------------------------------------------------
+
+        File manifestFile = archiveConfiguration.getManifestFile();
+
+        if ( manifestFile != null )
+        {
+            archiver.setManifest( manifestFile );
+        }
+
+        Manifest manifest = getManifest( project, archiveConfiguration.getManifest() );
+
+		// any custom manifest entries in the archive configuration manifest?
+		if (!archiveConfiguration.isManifestEntriesEmpty()) {
+			Map entries = archiveConfiguration.getManifestEntries();
+			Set keys = entries.keySet();
+			for (Iterator iter = keys.iterator(); iter.hasNext(); ) {
+				String key = (String) iter.next();
+				String value = (String) entries.get(key);
+				Manifest.Attribute attr = new Manifest.Attribute(key, value);
+				manifest.addConfiguredAttribute(attr);
+			}
+		}
+
+        // Configure the jar
+        archiver.addConfiguredManifest( manifest );
+
+        archiver.setCompress( archiveConfiguration.isCompress() );
+
+        archiver.setIndex( archiveConfiguration.isIndex() );
+
+        archiver.setDestFile( archiveFile );
+
+        // create archive
+        archiver.createArchive();
+
+        // Cleanup
+
+        pomPropertiesFile.delete();
+    }
+
+    private File writeExportReadyPom( MavenProject project )
+        throws IOException
+    {
+        String buildDirectory = project.getBuild().getDirectory();
+
+        File buildDirectoryFile = new File( buildDirectory );
+
+        buildDirectoryFile.mkdirs();
+
+        File fullPom = new File( buildDirectoryFile, "exported-pom.xml" );
+
+        FileWriter fWriter = null;
+
+        try
+        {
+            fWriter = new FileWriter( fullPom );
+
+            project.writeModel( fWriter );
+        }
+        finally
+        {
+            IOUtil.close( fWriter );
+        }
+
+        return fullPom;
+    }
+}