From 56e572665cba4b30f4b954e19c1ebabee5cc90d4 Mon Sep 17 00:00:00 2001 From: rsivaram Date: Sat, 26 Jul 2008 21:15:13 +0000 Subject: Version Tuscany modules and 3rd party libraries in itest/osgi-tuscany git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@680048 13f79535-47bb-0310-9956-ffa450edef68 --- .../test/osgi/runtime/impl/OSGiTestRuntime.java | 4 + java/sca/itest/osgi-tuscany/pom.xml | 1 + .../sca/installer/InstallerBundleActivator.java | 186 +++++- .../itest/osgi-tuscany/tuscany-versioned/pom.xml | 644 +++++++++++++++++++++ java/sca/modules/sca-api/pom.xml | 2 +- .../maven/maven-tuscany-bundle-plugin/pom.xml | 77 +++ .../bundle/plugin/TuscanyBundlePluginMojo.java | 492 ++++++++++++++++ 7 files changed, 1402 insertions(+), 4 deletions(-) create mode 100644 java/sca/itest/osgi-tuscany/tuscany-versioned/pom.xml create mode 100644 java/sca/tools/maven/maven-tuscany-bundle-plugin/pom.xml create mode 100644 java/sca/tools/maven/maven-tuscany-bundle-plugin/src/main/java/org/apache/tuscany/tools/sca/tuscany/bundle/plugin/TuscanyBundlePluginMojo.java (limited to 'java') diff --git a/java/sca/itest/osgi-tuscany/osgi-tuscany-test/src/main/java/org/apache/tuscany/sca/test/osgi/runtime/impl/OSGiTestRuntime.java b/java/sca/itest/osgi-tuscany/osgi-tuscany-test/src/main/java/org/apache/tuscany/sca/test/osgi/runtime/impl/OSGiTestRuntime.java index 6362385a13..6356718fe5 100644 --- a/java/sca/itest/osgi-tuscany/osgi-tuscany-test/src/main/java/org/apache/tuscany/sca/test/osgi/runtime/impl/OSGiTestRuntime.java +++ b/java/sca/itest/osgi-tuscany/osgi-tuscany-test/src/main/java/org/apache/tuscany/sca/test/osgi/runtime/impl/OSGiTestRuntime.java @@ -134,12 +134,15 @@ public abstract class OSGiTestRuntime { "javax.xml.xpath, " + "javax.sql," + "org.w3c.dom, " + + "org.w3c.dom.bootstrap, " + + "org.w3c.dom.ls, " + "org.xml.sax, " + "org.xml.sax.ext, " + "org.xml.sax.helpers, " + "javax.security.auth, " + "javax.security.auth.login, " + "javax.security.auth.callback, " + + "javax.security.cert, " + "javax.naming, " + "javax.naming.spi, " + "javax.naming.directory, " + @@ -147,6 +150,7 @@ public abstract class OSGiTestRuntime { "javax.imageio, " + "sun.misc, " + "javax.net, " + + "javax.net.ssl, " + "javax.crypto, " + "javax.rmi, " + "javax.transaction, " + diff --git a/java/sca/itest/osgi-tuscany/pom.xml b/java/sca/itest/osgi-tuscany/pom.xml index 4b432782a9..0da4f09d61 100644 --- a/java/sca/itest/osgi-tuscany/pom.xml +++ b/java/sca/itest/osgi-tuscany/pom.xml @@ -31,6 +31,7 @@ test-bundles + tuscany-versioned tuscany-osgi-installer osgi-tuscany-test diff --git a/java/sca/itest/osgi-tuscany/tuscany-osgi-installer/src/main/java/org/apache/tuscany/sca/installer/InstallerBundleActivator.java b/java/sca/itest/osgi-tuscany/tuscany-osgi-installer/src/main/java/org/apache/tuscany/sca/installer/InstallerBundleActivator.java index 2366acd094..059200302c 100644 --- a/java/sca/itest/osgi-tuscany/tuscany-osgi-installer/src/main/java/org/apache/tuscany/sca/installer/InstallerBundleActivator.java +++ b/java/sca/itest/osgi-tuscany/tuscany-osgi-installer/src/main/java/org/apache/tuscany/sca/installer/InstallerBundleActivator.java @@ -77,9 +77,28 @@ public class InstallerBundleActivator implements BundleActivator { }; + private static final String[] rebundleJars = { + "org.apache.tuscany.sdo", // Recreate export statements + }; + public void start(BundleContext bundleContext) throws Exception { + + String tuscanyHome = System.getProperty("TUSCANY_HOME"); + if (tuscanyHome == null) { + File homeDir = new File("../tuscany-versioned/target/classes"); + if (homeDir.exists()) { + tuscanyHome = homeDir.getCanonicalPath(); + } + } - installTuscanyIntoOSGi(bundleContext); + if (tuscanyHome == null) { + System.out.println("Installing Tuscany bundles and virtual 3rd party bundles."); + installTuscanyIntoOSGi(bundleContext); + } + else { + System.out.println("Installing Tuscany from TUSCANY_HOME=" + tuscanyHome); + installVersionedTuscanyIntoOSGi(bundleContext, tuscanyHome); + } } public void stop(BundleContext bundleContext) throws Exception { @@ -92,6 +111,75 @@ public class InstallerBundleActivator implements BundleActivator { } } } + + private void installVersionedTuscanyIntoOSGi(BundleContext bundleContext, String tuscanyHome) { + + try { + Bundle[] installedBundles = bundleContext.getBundles(); + HashSet installedBundleSet = new HashSet(); + for (Bundle bundle : installedBundles) { + if (bundle.getSymbolicName() != null) + installedBundleSet.add(bundle.getSymbolicName()); + } + + // FIXME: SDO bundles dont have the correct dependencies + System.setProperty("commonj.sdo.impl.HelperProvider", "org.apache.tuscany.sdo.helper.HelperProviderImpl"); + + HashSet tuscanyJars = new HashSet(); + HashSet thirdPartyJars = new HashSet(); + + + File tuscanyInstallDir = new File(tuscanyHome).getCanonicalFile(); + findBundles(bundleContext, tuscanyInstallDir, tuscanyJars, thirdPartyJars); + + + for (File bundleFile : thirdPartyJars) { + + String bundleName = bundleFile.getName(); + if (bundleName.startsWith("org.apache.felix")) + continue; + + boolean installed = false; + for (String name : rebundleJars) { + if (bundleName.startsWith(name)) { + rebundleAndInstall(bundleContext, tuscanyInstallDir, bundleFile); + installed = true; + } + } + if (installed) + continue; + + bundleContext.installBundle(bundleFile.toURI().toURL().toString()); + + } + + Bundle osgiRuntimeBundle = null; + for (File bundleFile : tuscanyJars) { + Bundle bundle = bundleContext.installBundle(bundleFile.toURI().toURL().toString()); + if ("org.apache.tuscany.sca.osgi.runtime".equals(bundle.getSymbolicName())) + osgiRuntimeBundle = bundle; + } + if (osgiRuntimeBundle != null) + osgiRuntimeBundle.start(); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void rebundleAndInstall(BundleContext bundleContext, File tuscanyInstallDir, File bundleFile) throws Exception { + String bundleSymbolicName = "org.apache.tuscany.sca.3rdparty." + bundleFile.getName(); + if (bundleSymbolicName.endsWith(".jar")) bundleSymbolicName = bundleSymbolicName.substring(0, bundleSymbolicName.length()-4); + + String bundleLocation = bundleFile.toURI().toURL().toString(); + InputStream bundleManifestStream = updateBundleManifest(bundleFile, bundleSymbolicName); + HashSet jarSet = new HashSet(); + jarSet.add(bundleFile); + + File newBundleFile = new File(tuscanyInstallDir, "org.apache.tuscany.sca." + bundleFile.getName()); + createAndInstallBundle(bundleContext, bundleLocation, newBundleFile, bundleManifestStream, jarSet); + bundleManifestStream.close(); + } private void installTuscanyIntoOSGi(BundleContext bundleContext) { @@ -167,6 +255,98 @@ public class InstallerBundleActivator implements BundleActivator { e.printStackTrace(); } } + + private void findBundles(BundleContext bundleContext, + File tuscanyInstallDir, + HashSet tuscanyJars, + HashSet thirdPartyJars) + throws IOException + { + + File[] jars = tuscanyInstallDir.listFiles(); + for (File jar : jars) { + String jarName = jar.getName(); + if (!jarName.endsWith(".jar")) + continue; + + if (!jarName.startsWith("org.apache.tuscany.sca")) { + if (jarName.endsWith(".jar")) + { + thirdPartyJars.add(jar); + } + } else { + boolean installTuscanyJar = true; + for (String name : tuscanyModulesToIgnore) { + name = name.replaceAll("-", "."); + if (jarName.startsWith("org.apache.tuscany.sca." + name)) { + installTuscanyJar = false; + break; + } + } + if (installTuscanyJar) + tuscanyJars.add(jar); + } + } + } + + + private InputStream updateBundleManifest(File jarFile, String bundleSymbolicName) throws Exception { + + if (!jarFile.exists()) + return null; + JarInputStream jar = new JarInputStream(new FileInputStream(jarFile)); + Manifest manifest = jar.getManifest(); + if (manifest == null) { + ZipEntry ze; + while ((ze = jar.getNextEntry()) != null) { + if (ze.getName().equals("META-INF/MANIFEST.MF")) + break; + } + if (ze != null) { + byte[] bytes = new byte[(int)ze.getSize()]; + jar.read(bytes); + manifest = new Manifest(new ByteArrayInputStream(bytes)); + } + } + if (manifest == null) { + manifest = new Manifest(); + } + + String bundleName = jarFile.getName(); + boolean isImmutableJar = false; + for (String immutableJar : immutableJars) { + if (bundleName.startsWith(immutableJar)) { + isImmutableJar = true; + break; + } + } + Attributes attributes = manifest.getMainAttributes(); + if (isImmutableJar) + attributes.putValue("Bundle-ClassPath", bundleName); + + + attributes.remove(new Attributes.Name("Require-Bundle")); + attributes.putValue("DynamicImport-Package", "*"); + + // Existing export statements in bundles may contain versions, so they should be used as is + // SDO exports are not sufficient, and should be changed + if (attributes.getValue("Export-Package") == null || bundleName.startsWith("org.apache.tuscany.sdo.tuscany-sdo-impl")) { + + HashSet packages = getPackagesInJar(bundleName, jar); + String version = getJarVersion(bundleName); + + attributes.putValue("Export-Package", packagesToString(packages, version)); + attributes.putValue("Import-Package", packagesToString(packages, null)); + } + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + manifest.write(out); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + out.close(); + + return in; + + } private void findJars(BundleContext bundleContext, HashSet tuscanyJars, @@ -222,10 +402,10 @@ public class InstallerBundleActivator implements BundleActivator { tuscanyJars.add(jar); } } - - } + + private File findTuscanyInstallDir(Bundle installerBundle) throws IOException { diff --git a/java/sca/itest/osgi-tuscany/tuscany-versioned/pom.xml b/java/sca/itest/osgi-tuscany/tuscany-versioned/pom.xml new file mode 100644 index 0000000000..2a0ff0dcc8 --- /dev/null +++ b/java/sca/itest/osgi-tuscany/tuscany-versioned/pom.xml @@ -0,0 +1,644 @@ + + + + 4.0.0 + + org.apache.tuscany.sca + tuscany-itest + 1.4-SNAPSHOT + ../../pom.xml + + itest-osgi-tuscany-versioned + Apache Tuscany OSGi - Versioned Tuscany Bundles + + + true + ${pom.version} + + + + + ${pom.groupId} + tuscany-monitor-logging + ${pom.version} + + + ${pom.groupId} + tuscany-assembly + ${pom.version} + + + ${pom.groupId} + tuscany-assembly-xml + ${pom.version} + + + ${pom.groupId} + tuscany-assembly-xsd + ${pom.version} + + + ${pom.groupId} + tuscany-binding-dwr + ${pom.version} + + + ${pom.groupId} + tuscany-binding-ejb-runtime + ${pom.version} + + + ${pom.groupId} + tuscany-binding-atom + ${pom.version} + + + + ${pom.groupId} + tuscany-binding-feed + ${pom.version} + + + ${pom.groupId} + tuscany-binding-rss + ${pom.version} + + + ${pom.groupId} + tuscany-binding-rss-rome + ${pom.version} + + + ${pom.groupId} + tuscany-binding-http-runtime + ${pom.version} + + + ${pom.groupId} + tuscany-binding-jms-runtime + ${pom.version} + + + org.apache.activemq + apache-activemq + 4.1.1 + + + commons-httpclient + commons-httpclient + + + commons-fileupload + commons-fileupload + + + commons-beanutils + commons-beanutils + + + org.apache.activemq + activemq-console + + + org.apache.activemq + activemq-core + + + org.apache.activemq + activemq-optional + + + org.apache.activemq + activemq-web + + + org.apache.activemq + activemq-web-demo + + + org.apache.activemq + activemq-jaas + + + org.apache.geronimo.specs + geronimo-j2ee-connector_1.5_spec + + + org.apache.geronimo.specs + geronimo-j2ee-jacc_1.0_spec + + + org.apache.geronimo.specs + geronimo-jms_1.1_spec + + + org.apache.geronimo.specs + geronimo-jsp_2.0_spec + + + org.apache.geronimo.specs + geronimo-j2ee-management_1.0_spec + + + org.mortbay.jetty + servlet-api-2.5 + + + org.mortbay.jetty + jetty + + + org.mortbay.jetty + jetty-util + + + xerces + xercesImpl + + + backport-util-concurrent + backport-util-concurrent + + + activesoap + jaxp-api + + + activemq + jmdns + + + jrms + jrms + + + xerces + xmlParserAPIs + + + xstream + xstream + + + xmlpull + xmlpull + + + mx4j + mx4j + + + mx4j + mx4j-remote + + + + + ${pom.groupId} + tuscany-binding-jsonrpc-runtime + ${pom.version} + + + ${pom.groupId} + tuscany-binding-notification + ${pom.version} + + + ${pom.groupId} + tuscany-binding-rmi + ${pom.version} + + + ${pom.groupId} + tuscany-binding-sca + ${pom.version} + + + ${pom.groupId} + tuscany-binding-sca-axis2 + ${pom.version} + + + ${pom.groupId} + tuscany-binding-sca-xml + ${pom.version} + + + ${pom.groupId} + tuscany-binding-ws + ${pom.version} + + + ${pom.groupId} + tuscany-binding-ws-axis2 + ${pom.version} + + + ${pom.groupId} + tuscany-binding-ws-xml + ${pom.version} + + + ${pom.groupId} + tuscany-contribution + ${pom.version} + + + ${pom.groupId} + tuscany-contribution-groovy + ${pom.version} + + + ${pom.groupId} + tuscany-contribution-impl + ${pom.version} + + + ${pom.groupId} + tuscany-contribution-java + ${pom.version} + + + ${pom.groupId} + tuscany-contribution-namespace + ${pom.version} + + + ${pom.groupId} + tuscany-core + ${pom.version} + + + ${pom.groupId} + tuscany-core-databinding + ${pom.version} + + + ${pom.groupId} + tuscany-core-spi + ${pom.version} + + + ${pom.groupId} + tuscany-databinding + ${pom.version} + + + ${pom.groupId} + tuscany-databinding-axiom + ${pom.version} + + + ${pom.groupId} + tuscany-databinding-fastinfoset + ${pom.version} + + + ${pom.groupId} + tuscany-databinding-jaxb + ${pom.version} + + + ${pom.groupId} + tuscany-databinding-sdo + ${pom.version} + + + ${pom.groupId} + tuscany-databinding-sdo-axiom + ${pom.version} + + + ${pom.groupId} + tuscany-databinding-xmlbeans + ${pom.version} + + + ${pom.groupId} + tuscany-databinding-xstream + ${pom.version} + + + ${pom.groupId} + tuscany-host-embedded + ${pom.version} + + + ${pom.groupId} + tuscany-host-http + ${pom.version} + + + ${pom.groupId} + tuscany-host-rmi + ${pom.version} + + + ${pom.groupId} + tuscany-host-webapp + ${pom.version} + + + ${pom.groupId} + tuscany-host-jetty + ${pom.version} + + + ${pom.groupId} + tuscany-interface + ${pom.version} + + + ${pom.groupId} + tuscany-interface-java + ${pom.version} + + + ${pom.groupId} + tuscany-interface-java-xml + ${pom.version} + + + ${pom.groupId} + tuscany-interface-wsdl + ${pom.version} + + + ${pom.groupId} + tuscany-interface-wsdl-xml + ${pom.version} + + + + ${pom.groupId} + tuscany-implementation-das + ${pom.version} + + + ${pom.groupId} + tuscany-implementation-ejb + ${pom.version} + + + ${pom.groupId} + tuscany-implementation-ejb + ${pom.version} + + + ${pom.groupId} + tuscany-implementation-java + ${pom.version} + + + ${pom.groupId} + tuscany-implementation-java-xml + ${pom.version} + + + ${pom.groupId} + tuscany-implementation-java-runtime + ${pom.version} + + + ${pom.groupId} + tuscany-implementation-node + ${pom.version} + + + ${pom.groupId} + tuscany-implementation-node-runtime + ${pom.version} + + + ${pom.groupId} + tuscany-host-tomcat + + + + + ${pom.groupId} + tuscany-implementation-osgi + ${pom.version} + + + ${pom.groupId} + tuscany-implementation-resource-runtime + ${pom.version} + + + ${pom.groupId} + tuscany-implementation-script + ${pom.version} + + + groovy + groovy-all-minimal + + + + + ${pom.groupId} + tuscany-implementation-spring + ${pom.version} + + + ${pom.groupId} + tuscany-implementation-xquery + ${pom.version} + + + ${pom.groupId} + tuscany-implementation-widget-runtime + ${pom.version} + + + ${pom.groupId} + tuscany-node2-api + ${pom.version} + + + ${pom.groupId} + tuscany-node2-impl + ${pom.version} + + + ${pom.groupId} + tuscany-node2-launcher + ${pom.version} + + + ${pom.groupId} + tuscany-policy + ${pom.version} + + + ${pom.groupId} + tuscany-policy-logging + ${pom.version} + + + ${pom.groupId} + tuscany-policy-security + ${pom.version} + + + ${pom.groupId} + tuscany-policy-xml + ${pom.version} + + + ${pom.groupId} + tuscany-definitions + ${pom.version} + + + ${pom.groupId} + tuscany-workspace + ${pom.version} + + + ${pom.groupId} + tuscany-domain-manager + ${pom.version} + + + ${pom.groupId} + tuscany-host-tomcat + + + + + ${pom.groupId} + tuscany-workspace-impl + ${pom.version} + + + ${pom.groupId} + tuscany-workspace-xml + ${pom.version} + + + + ${pom.groupId} + tuscany-sca-api + ${pom.version} + + + org.apache.tuscany.sdo + tuscany-sdo-impl + 1.1-incubating + + + org.codehaus.woodstox + wstx-asl + + + + + org.apache.tuscany.sdo + tuscany-sdo-tools + 1.1-incubating + + + + com.sun.xml.bind + jaxb-impl + 2.1.6 + + + javax.xml.stream + stax-api + + + + + commons-lang + commons-lang + 2.1 + + + commons-cli + commons-cli + 1.0 + + + junit + junit + + + + + org.easymock + easymock + 2.2 + + + + + + + + org.apache.tuscany.sca + tuscany-maven-bundle-plugin + 1.4-SNAPSHOT + true + + + + execute + + + + + + + + + + diff --git a/java/sca/modules/sca-api/pom.xml b/java/sca/modules/sca-api/pom.xml index f345c6aa5c..54e43ce91c 100644 --- a/java/sca/modules/sca-api/pom.xml +++ b/java/sca/modules/sca-api/pom.xml @@ -40,7 +40,7 @@ - 2.0 + 1.4 org.apache.tuscany.sca.api ${pom.description} org.osoa.sca* diff --git a/java/sca/tools/maven/maven-tuscany-bundle-plugin/pom.xml b/java/sca/tools/maven/maven-tuscany-bundle-plugin/pom.xml new file mode 100644 index 0000000000..b7eec4f2aa --- /dev/null +++ b/java/sca/tools/maven/maven-tuscany-bundle-plugin/pom.xml @@ -0,0 +1,77 @@ + + + + 4.0.0 + + org.apache.tuscany.sca + tuscany-sca-maven-tools + 1.4-SNAPSHOT + ../pom.xml + + tuscany-maven-bundle-plugin + maven-plugin + Apache Tuscany SCA Maven OSGi Bundle Plugin + + + + org.apache.maven + maven-plugin-api + 2.0.7 + + + + org.apache.maven + maven-project + 2.0.7 + + + + org.apache.maven + maven-settings + 2.0.7 + + + + org.apache.maven + maven-artifact + 2.0.7 + + + + org.apache.maven + maven-model + 2.0.7 + + + + org.apache.maven.shared + maven-dependency-tree + 1.1 + + + + org.apache.felix + maven-bundle-plugin + 1.4.1 + + + + + diff --git a/java/sca/tools/maven/maven-tuscany-bundle-plugin/src/main/java/org/apache/tuscany/tools/sca/tuscany/bundle/plugin/TuscanyBundlePluginMojo.java b/java/sca/tools/maven/maven-tuscany-bundle-plugin/src/main/java/org/apache/tuscany/tools/sca/tuscany/bundle/plugin/TuscanyBundlePluginMojo.java new file mode 100644 index 0000000000..64f99a38d3 --- /dev/null +++ b/java/sca/tools/maven/maven-tuscany-bundle-plugin/src/main/java/org/apache/tuscany/tools/sca/tuscany/bundle/plugin/TuscanyBundlePluginMojo.java @@ -0,0 +1,492 @@ +/* + * 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.tools.sca.tuscany.bundle.plugin; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.Collection; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.jar.Attributes; +import java.util.jar.JarInputStream; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; +import java.util.zip.ZipEntry; + +import org.apache.felix.bundleplugin.BundleAllPlugin; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.factory.ArtifactFactory; +import org.apache.maven.artifact.metadata.ArtifactMetadataSource; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.artifact.resolver.ArtifactCollector; +import org.apache.maven.artifact.resolver.ArtifactNotFoundException; +import org.apache.maven.artifact.resolver.ArtifactResolutionException; +import org.apache.maven.artifact.resolver.ArtifactResolver; +import org.apache.maven.artifact.versioning.OverConstrainedVersionException; +import org.apache.maven.artifact.versioning.VersionRange; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.MavenProjectBuilder; +import org.apache.maven.project.ProjectBuildingException; +import org.apache.maven.project.artifact.InvalidDependencyVersionException; +import org.apache.maven.shared.dependency.tree.DependencyTree; +import org.apache.maven.shared.dependency.tree.DependencyTreeBuilder; +import org.apache.maven.shared.dependency.tree.DependencyTreeBuilderException; +import org.apache.maven.shared.osgi.Maven2OsgiConverter; +import org.osgi.framework.Version; + +import aQute.lib.header.OSGiHeader; + +/** + * @version $$ + * @goal execute + * @phase compile + * @requiresDependencyResolution test + * @description Generate versioned OSGi bundles corresponding to Tuscany modules and all 3rd party dependencies + */ +public class TuscanyBundlePluginMojo extends BundleAllPlugin { + /** + * The maven project + * + * @parameter expression="${project}" + * @required + */ + private MavenProject project; + + /** + * Directory containing pom. + * + * @parameter expression="${basedir}" + * @required + */ + private File baseDir; + + /** + * Build directory for project + * + * @parameter expression="${project.build.directory}" + * @required + */ + private String buildDirectory; + + /** + * Output directory where bundles are generated. + * + * @parameter expression="${project.build.outputDirectory}" + * @required + */ + private File outputDirectory; + + /** + * Artifact resolver + * + * @component + */ + private ArtifactResolver artifactResolver; + + /** + * Artifact factory + * + * @component + */ + private ArtifactFactory artifactFactory; + + /** + * @component + */ + private ArtifactMetadataSource artifactMetadataSource; + + /** + * Dependency tree builder + * + * @component + */ + private DependencyTreeBuilder dependencyTreeBuilder; + + /** + * @component + */ + private ArtifactCollector collector; + + /** + * @component + */ + private MavenProjectBuilder mavenProjectBuilder; + + /** + * The local repository + * + * @parameter expression="${localRepository}" + * @required + */ + private ArtifactRepository localRepository; + + /** + * The remote repositories + * + * @parameter expression="${project.remoteArtifactRepositories}" + */ + private List remoteRepositories; + + /** + * @component + */ + private Maven2OsgiConverter maven2OsgiConverter; + + private static final HashSet dependenciesToIgnore = new HashSet(); + private static final HashSet importDirectives = new HashSet(); + private static final HashSet exportDirectives = new HashSet(); + private static final Hashtable privatePackages = new Hashtable(); + private static final Hashtable dynamicImports = new Hashtable(); + + static { + importDirectives.add("resolution"); + + exportDirectives.add("uses"); + exportDirectives.add("mandatory"); + exportDirectives.add("include"); + exportDirectives.add("exclude"); + + dependenciesToIgnore.add("xml-apis:xml-apis"); + dependenciesToIgnore.add("stax:stax-api"); + + + // Comma separated list of packages + privatePackages.put("org.apache.woden:woden", "javax.xml.namespace"); + privatePackages.put("org.apache.xmlbeans:xmlbeans", "org.w3c.dom"); + privatePackages.put("org.apache.axis2:axis2-adb", "org.apache.axis2.util"); + privatePackages.put("org.apache.axis2:addressing", "org.apache.axis2.addressing"); + privatePackages.put("org.apache.axis2:axis2-kernel", "org.apache.axis2.wsdl"); + privatePackages.put("org.apache.bsf:bsf-all", "org.mozilla.javascript"); + privatePackages.put("org.apache.axis2:axis2-codegen", "org.apache.axis2.wsdl,org.apache.axis2.wsdl.util"); + + dynamicImports.put("org.apache.ws.commons.axiom:axiom-api", "org.apache.axiom.om.impl.*,org.apache.axiom.soap.impl.*"); + dynamicImports.put("org.apache.bsf:bsf-all", "org.mozilla.*"); + dynamicImports.put("org.apache.santuario:xmlsec", "org.apache.ws.security.*"); + } + + + @SuppressWarnings("unchecked") + public void execute() throws MojoExecutionException { + try { + + setBasedir(baseDir); + setBuildDirectory(buildDirectory); + setOutputDirectory(outputDirectory); + setMaven2OsgiConverter(maven2OsgiConverter); + try { + Field importField = this.getClass().getSuperclass().getDeclaredField("wrapImportPackage"); + importField.setAccessible(true); + importField.set(this, "*;resolution:=optional"); + } catch (Exception e2) { + e2.printStackTrace(); + getLog().error("Could not set import instructions"); + } + + + DependencyTree dependencyTree = dependencyTreeBuilder.buildDependencyTree(project, + localRepository, artifactFactory, + artifactMetadataSource, collector ); + + Hashtable duplicateWarnings = new Hashtable(); + Hashtable artifactsToBundle = new Hashtable(); + + for (Object a : dependencyTree.getArtifacts()) { + Artifact artifact = (Artifact)a; + + if (project.getArtifactId().equals(artifact.getArtifactId()) && project.getGroupId().equals(artifact.getGroupId())) + continue; + + if (Artifact.SCOPE_SYSTEM.equals(artifact.getScope())||Artifact.SCOPE_TEST.equals(artifact.getScope())) + continue; + + String id = artifact.getGroupId() + ":" + artifact.getArtifactId(); + if (dependenciesToIgnore.contains(id)) + continue; + + Artifact old = artifactsToBundle.get(id); + if (old != null && !old.getVersion().equals(artifact.getVersion())) { + String oldVersion = old.getVersion(); + String thisVersion = artifact.getVersion(); + if (!thisVersion.equals(duplicateWarnings.get(oldVersion))&&!oldVersion.equals(duplicateWarnings.get(thisVersion))) { + getLog().warn("Multiple versions of artifacts : " + old + ", " + artifact); + duplicateWarnings.put(oldVersion, thisVersion); + } + + } + + VersionRange versionRange = artifact.getVersionRange(); + if (versionRange == null) + versionRange = VersionRange.createFromVersion(artifact.getVersion()); + + Artifact dependencyArtifact = artifactFactory.createDependencyArtifact(artifact.getGroupId(), + artifact.getArtifactId(), + versionRange, + artifact.getType(), + artifact.getClassifier(), + artifact.getScope()); + + try { + if (old != null && old.getSelectedVersion().compareTo(artifact.getSelectedVersion()) >= 0) + continue; + else + artifactsToBundle.remove(id); + } catch (OverConstrainedVersionException e1) { + getLog().warn("Could not process maven version for artifact " + artifact); + continue; + } + + try { + artifactResolver.resolve(dependencyArtifact, remoteRepositories, localRepository); + } catch (ArtifactResolutionException e) { + getLog().warn("Artifact " + artifact + " could not be resolved."); + } catch (ArtifactNotFoundException e) { + getLog().warn("Artifact " + artifact + " could not be found."); + } + + artifact.setFile(dependencyArtifact.getFile()); + + artifactsToBundle.put(id, artifact); + + } + + bundleArtifacts(artifactsToBundle.values()); + + + } catch (DependencyTreeBuilderException e) { + throw new MojoExecutionException("Could not build dependency tree", e); + } catch (ProjectBuildingException e) { + throw new MojoExecutionException("Could not build project for artifact", e); + } catch (InvalidDependencyVersionException e) { + throw new MojoExecutionException("Invalid dependency version", e); + } catch (IOException e) { + throw new MojoExecutionException("Could not build bundle manifest", e); + } + } + + + private void bundleArtifacts(Collection artifacts) throws ProjectBuildingException, + InvalidDependencyVersionException, MojoExecutionException, IOException { + + for (Artifact artifact : artifacts) { + + artifact.setFile(getFile( artifact )); + + MavenProject bundleProject = mavenProjectBuilder.buildFromRepository(artifact, remoteRepositories, localRepository, true); + bundleProject.setArtifact(artifact); + + if ( bundleProject.getDependencyArtifacts() == null ) { + bundleProject.setDependencyArtifacts(bundleProject.createArtifacts(artifactFactory, null, null ) ); + } + + File outputFile = getOutputFile(bundleProject.getArtifact()); + if (outputFile.exists()) + outputFile.delete(); + bundle(bundleProject); + postProcessBundle(artifact, outputFile); + + } + } + + + @SuppressWarnings("unchecked") + private void postProcessBundle(Artifact artifact, File bundleFile) throws IOException { + + if (!bundleFile.exists()) + return; + + boolean retainManifestEntries = false; + if (!artifact.getGroupId().equals("org.apache.tuscany.sca")) { + // For pre-bundled 3rd party bundles, retain all OSGi manifest entries except Require-Bundle + Manifest manifest = getManifest(artifact.getFile()); + if (manifest != null && manifest.getMainAttributes() != null && + manifest.getMainAttributes().getValue("Bundle-SymbolicName") != null) { + retainManifestEntries = true; + } + } + + Manifest manifest = getManifest(bundleFile); + Attributes attributes = manifest.getMainAttributes(); + + if (attributes == null) { + return; + } + + String artifactId = artifact.getGroupId() + ":" + artifact.getArtifactId(); + + String bundleSymName = (String)attributes.getValue("Bundle-SymbolicName"); + if (!bundleSymName.startsWith("org.apache.tuscany.sca")) { + bundleSymName = "org.apache.tuscany.sca.3rdparty." + bundleSymName; + attributes.putValue("Bundle-SymbolicName", bundleSymName); + } + + String imports = (String)attributes.getValue("Import-Package"); + String exports = (String)attributes.getValue("Export-Package"); + + // For EMF jars + if (attributes.getValue("Require-Bundle") != null) { + attributes.remove(new Attributes.Name("Require-Bundle")); + attributes.putValue("DynamicImport-Package", "*"); + attributes.remove(new Attributes.Name("Eclipse-LazyStart")); + } + + if (!retainManifestEntries && imports != null) { + StringBuilder newImportBuf = new StringBuilder(); + Map importMap = OSGiHeader.parseHeader(imports); + for (Object pkg : importMap.keySet()) { + + if (isPrivatePackage(artifactId, (String)pkg)) { + continue; + } + + Map importAttr = (Map)importMap.get(pkg); + String version = (String)importAttr.get("version"); + if (version != null && version.indexOf(',') == -1) { + if (!version.matches(".*\\..*\\.")) { + Version curVersion = new Version(version); + Version nextVersion = new Version(curVersion.getMajor(), curVersion.getMinor()+1, 0); + version = '[' + version + ',' + nextVersion + ')'; + } + else + version = '[' + version + ',' + version + ']'; + importAttr.put("version", version); + } + updateManifestAttribute((String)pkg, importAttr, importDirectives, newImportBuf); + + } + attributes.putValue("Import-Package", newImportBuf.toString()); + } + + if (!retainManifestEntries && exports != null) { + StringBuilder newExportBuf = new StringBuilder(); + Map exportMap = OSGiHeader.parseHeader(exports); + + for (Object value : exportMap.keySet()) { + String pkg = (String)value; + if (!isPrivatePackage(artifactId, pkg)) { + Map exportAttr = (Map)exportMap.get(pkg); + updateManifestAttribute((String)pkg, exportAttr, exportDirectives, newExportBuf); + } + } + if (newExportBuf.length() > 0) + attributes.putValue("Export-Package", newExportBuf.toString()); + else + attributes.remove(new Attributes.Name("Export-Package")); + } + + String dynImport = dynamicImports.get(artifactId); + if (dynImport != null) + attributes.putValue("DynamicImport-Package", dynImport); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + JarOutputStream jarOut = new JarOutputStream(out, manifest); + copyJar(bundleFile, jarOut); + jarOut.close(); + out.close(); + bundleFile.delete(); + FileOutputStream fileOut = new FileOutputStream(bundleFile); + fileOut.write(out.toByteArray()); + fileOut.close(); + + } + + + private void copyJar(File file, JarOutputStream jarOut) throws IOException { + + try { + JarInputStream jarIn = new JarInputStream(new FileInputStream(file)); + ZipEntry ze; + byte[] readBuf = new byte[1000]; + int bytesRead; + while ((ze = jarIn.getNextEntry()) != null) { + if (ze.getName().equals("META-INF/MANIFEST.MF")) + continue; + jarOut.putNextEntry(ze); + while ((bytesRead = jarIn.read(readBuf)) > 0) { + jarOut.write(readBuf, 0, bytesRead); + } + } + jarIn.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private Manifest getManifest(File jar) { + try { + JarInputStream jarIn = new JarInputStream(new FileInputStream(jar)); + Manifest manifest = jarIn.getManifest(); + if (manifest == null) { + ZipEntry ze; + while ((ze = jarIn.getNextEntry()) != null) { + if (ze.getName().equals("META-INF/MANIFEST.MF")) + break; + } + if (ze != null) { + byte[] bytes = new byte[(int)ze.getSize()]; + jarIn.read(bytes); + manifest = new Manifest(new ByteArrayInputStream(bytes)); + } + } + jarIn.close(); + return manifest; + } catch (IOException e) { + return null; + } + } + + private boolean isPrivatePackage(String artifactId, String pkg) { + String privatePkgs = privatePackages.get(artifactId); + if (privatePkgs != null) { + String[] pkgs = privatePkgs.split(","); + for (int i = 0; i < pkgs.length; i++) { + if (pkgs[i].trim().equals(pkg)) + return true; + } + } + return false; + } + + + private void updateManifestAttribute(String pkg, Map newMap, Set directives, StringBuilder newAttrBuffer) { + if (newAttrBuffer.length() != 0) newAttrBuffer.append(','); + newAttrBuffer.append(pkg); + if (newMap.size() > 0) { + for (Object attrName : newMap.keySet()) { + newAttrBuffer.append(';'); + newAttrBuffer.append(attrName); + if (directives.contains(attrName)) + newAttrBuffer.append(":="); + else + newAttrBuffer.append('='); + newAttrBuffer.append('\"'); + newAttrBuffer.append(newMap.get(attrName)); + newAttrBuffer.append('\"'); + } + } + } +} \ No newline at end of file -- cgit v1.2.3