diff options
author | rfeng <rfeng@13f79535-47bb-0310-9956-ffa450edef68> | 2010-01-05 18:00:36 +0000 |
---|---|---|
committer | rfeng <rfeng@13f79535-47bb-0310-9956-ffa450edef68> | 2010-01-05 18:00:36 +0000 |
commit | 845740951bf395da58f984eaf3fea6f8187b922b (patch) | |
tree | ed58bbb22b41c528be304a71268d66fb8b476874 /maven-plugins/trunk/maven-bundle-plugin/src/main/java/org/apache/tuscany/maven/bundle/plugin/BundleAggregatorMojo.java | |
parent | db11acb8fcf7e01c1d983cbf0c6fb4f7e8072885 (diff) |
Add new goal so that we can generate a single OSGi bundle from the modules
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@896154 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'maven-plugins/trunk/maven-bundle-plugin/src/main/java/org/apache/tuscany/maven/bundle/plugin/BundleAggregatorMojo.java')
-rw-r--r-- | maven-plugins/trunk/maven-bundle-plugin/src/main/java/org/apache/tuscany/maven/bundle/plugin/BundleAggregatorMojo.java | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/maven-plugins/trunk/maven-bundle-plugin/src/main/java/org/apache/tuscany/maven/bundle/plugin/BundleAggregatorMojo.java b/maven-plugins/trunk/maven-bundle-plugin/src/main/java/org/apache/tuscany/maven/bundle/plugin/BundleAggregatorMojo.java new file mode 100644 index 0000000000..c0952ad222 --- /dev/null +++ b/maven-plugins/trunk/maven-bundle-plugin/src/main/java/org/apache/tuscany/maven/bundle/plugin/BundleAggregatorMojo.java @@ -0,0 +1,263 @@ +/* + * 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.tuscany.maven.bundle.plugin; + +import static org.apache.tuscany.maven.bundle.plugin.AggregatedBundleActivator.BUNDLE_ACTIVATOR_LIST; +import static org.apache.tuscany.maven.bundle.plugin.HeaderParser.merge; +import static org.osgi.framework.Constants.BUNDLE_ACTIVATOR; +import static org.osgi.framework.Constants.BUNDLE_CLASSPATH; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.jar.Attributes; +import java.util.jar.JarFile; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; +import java.util.zip.ZipEntry; + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.project.MavenProject; +import org.apache.tuscany.maven.bundle.plugin.HeaderParser.HeaderClause; + +/** + * @version $Rev$ $Date$ + * @goal aggregate-modules + * @phase process-resources + * @requiresDependencyResolution test + * @description Generate an aggregated bundle that contains all the modules and 3rd party jars + */ +public class BundleAggregatorMojo extends AbstractMojo { + /** + * The project to create a distribution for. + * + * @parameter expression="${project}" + * @required + * @readonly + */ + private MavenProject project; + + /** + * Root directory. + * + * @parameter expression="${project.build.directory}/modules" + */ + private File rootDirectory; + + /** + * Aggregated bundle + * + * @parameter expression="${project.build.directory}/singlebundle/tuscany-bundle.jar" + */ + private File targetBundleFile; + + /** + * @parameter default-value== "org.apache.tuscany.sca.bundle"; + */ + private String bundleName = "org.apache.tuscany.sca.bundle"; + + /** + * @parameter default-value== "2.0.0"; + */ + private String bundleVersion = "2.0.0"; + + // private static final Logger logger = Logger.getLogger(BundleAggregatorMojo.class.getName()); + + public void aggregateBundles(File root, File targetBundleFile) throws Exception { + Log log = getLog(); + if (!root.isDirectory()) { + log.warn(root + " is not a directory"); + return; + } + targetBundleFile.getParentFile().mkdirs(); + Set<File> jarFiles = new HashSet<File>(); + List<Manifest> manifests = new ArrayList<Manifest>(); + for (File child : root.listFiles()) { + try { + Manifest manifest = null; + if (child.isDirectory()) { + File mf = new File(child, "META-INF/MANIFEST.MF"); + if (mf.isFile()) { + FileInputStream is = new FileInputStream(mf); + manifest = new Manifest(is); + is.close(); + if (manifest != null) { + String classpath = manifest.getMainAttributes().getValue("Bundle-ClassPath"); + if (classpath != null) { + for (HeaderClause clause : HeaderParser.parse(classpath)) { + if (clause.getValue().equals(".")) { + continue; + } else { + jarFiles.add(new File(child, clause.getValue())); + } + } + } else { + // + } + } + } + } else if (child.getName().endsWith(".jar")) { + JarFile jar = new JarFile(child); + manifest = jar.getManifest(); + jar.close(); + if (manifest != null) { + String id = manifest.getMainAttributes().getValue("Bundle-SymbolicName"); + if (id != null && (id.startsWith("org.eclipse.") || id + .startsWith("org.apache.tuscany.sca.gateway"))) { + manifest = null; + } else { + jarFiles.add(child); + } + } + } + if (manifest == null) { + continue; + } + + log.debug("Bundle file: " + child); + manifests.add(manifest); + } catch (Exception e) { + throw e; + } + } + Manifest merged = new Manifest(); + Attributes attributes = merged.getMainAttributes(); + attributes.putValue("Manifest-Version", "1.0"); + attributes.putValue("Bundle-ManifestVersion", "2"); + attributes.putValue("Bundle-License", "http://www.apache.org/licenses/LICENSE-2.0.txt"); + attributes.putValue("Bundle-DocURL", "http://www.apache.org/"); + attributes.putValue("Bundle-RequiredExecutionEnvironment", "J2SE-1.5,JavaSE-1.6"); + attributes.putValue("Bundle-Vendor", "The Apache Software Foundation"); + attributes.putValue("Bundle-Version", bundleVersion); + attributes.putValue("Bundle-SymbolicName", bundleName); + attributes.putValue("SCA-Version", "1.1"); + attributes.putValue("Bundle-Name", bundleName); + attributes.putValue("Bundle-ActivationPolicy", "lazy"); + for (Manifest mf : manifests) { + for (Map.Entry<Object, Object> e : mf.getMainAttributes().entrySet()) { + Attributes.Name key = (Attributes.Name)e.getKey(); + String name = key.toString(); + String oldValue = attributes.getValue(name); + String value = (String)e.getValue(); + if (name.equals("Export-Package") || name.equals("Import-Package") + || name.equals("Require-Bundle") + || name.equals("DynamicImport-Package") + || name.equals("Bundle-ClassPath") + || name.equals("Private-Package") + || name.equals("Bundle-Description")) { + attributes.putValue(name, merge(oldValue, value)); + } else if (name.equals(BUNDLE_ACTIVATOR)) { + oldValue = attributes.getValue(BUNDLE_ACTIVATOR_LIST); + attributes.putValue(BUNDLE_ACTIVATOR_LIST, merge(oldValue, value)); + } else if (name.equals("Main-Class") || name.startsWith("Eclipse-") || name.startsWith("Bundle-")) { + // Ignore + } else { + // Ignore + // attributes.putValue(name, value); + } + } + } + log.info("Generating " + targetBundleFile); + attributes.putValue(BUNDLE_ACTIVATOR, AggregatedBundleActivator.class.getName()); + String bundleClassPath = attributes.getValue(BUNDLE_CLASSPATH); + bundleClassPath = merge(bundleClassPath, "."); + for (File f : jarFiles) { + bundleClassPath = merge(bundleClassPath, f.getName()); + } + attributes.putValue(BUNDLE_CLASSPATH, bundleClassPath); + + FileOutputStream fos = new FileOutputStream(targetBundleFile); + JarOutputStream bundle = new JarOutputStream(fos, merged); + + for (File file : jarFiles) { + log.info("Adding " + file); + addEntry(bundle, file.getName(), file); + } + + String classFile = AggregatedBundleActivator.class.getName().replace(".", "/") + ".class"; + InputStream classStream = BundleAggregatorMojo.class.getClassLoader().getResourceAsStream(classFile); + addEntry(bundle, classFile, classStream); + bundle.close(); + } + + private static void addDir(JarOutputStream jos, File root, File dir) throws IOException, FileNotFoundException { + for (File file : dir.listFiles()) { + if (file.isDirectory()) { + addDir(jos, root, file); + } else if (file.isFile()) { + // getLog().info(file.toString()); + String uri = root.toURI().relativize(file.toURI()).toString(); + if ("META-INF/MANIFEST.MF".equals(uri)) { + continue; + } + addEntry(jos, uri, file); + } + } + } + + private static void addEntry(JarOutputStream jos, String name, File file) throws IOException { + FileInputStream in = new FileInputStream(file); + addEntry(jos, name, in); + } + + private static final byte[] buf = new byte[4096]; + + private static void addEntry(JarOutputStream jos, String name, InputStream in) throws IOException { + ZipEntry entry = new ZipEntry(name); + jos.putNextEntry(entry); + for (;;) { + int len = in.read(buf); + if (len > 0) { + jos.write(buf, 0, len); + } else { + break; + } + } + in.close(); + jos.closeEntry(); + } + + private static void generateJar(File root, File jar, Manifest mf) throws IOException { + FileOutputStream fos = new FileOutputStream(jar); + JarOutputStream jos = mf != null ? new JarOutputStream(fos, mf) : new JarOutputStream(fos); + addDir(jos, root, root); + jos.close(); + } + + public void execute() throws MojoExecutionException, MojoFailureException { + try { + aggregateBundles(rootDirectory, targetBundleFile); + } catch (Exception e) { + throw new MojoExecutionException(e.getMessage(), e); + } + + } +} |