From 1030d70e3c96f5929249e21f1c0dbe4af8c943df Mon Sep 17 00:00:00 2001 From: antelder Date: Thu, 5 Mar 2009 08:13:34 +0000 Subject: Test tag git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@750366 13f79535-47bb-0310-9956-ffa450edef68 --- .../maven/bundle/plugin/ArtifactAggregation.java | 73 ++ .../maven/bundle/plugin/ArtifactMember.java | 61 ++ .../tuscany/maven/bundle/plugin/BundleUtil.java | 408 ++++++++++ .../bundle/plugin/ModuleBundlesBuildMojo.java | 834 +++++++++++++++++++++ .../maven/bundle/plugin/OSGIArtifactVersion.java | 232 ++++++ .../bundle/plugin/ThirdPartyBundleBuildMojo.java | 152 ++++ 6 files changed, 1760 insertions(+) create mode 100644 maven-plugins/tags/maven-bundle-plugin-1.0.1/src/main/java/org/apache/tuscany/maven/bundle/plugin/ArtifactAggregation.java create mode 100644 maven-plugins/tags/maven-bundle-plugin-1.0.1/src/main/java/org/apache/tuscany/maven/bundle/plugin/ArtifactMember.java create mode 100644 maven-plugins/tags/maven-bundle-plugin-1.0.1/src/main/java/org/apache/tuscany/maven/bundle/plugin/BundleUtil.java create mode 100644 maven-plugins/tags/maven-bundle-plugin-1.0.1/src/main/java/org/apache/tuscany/maven/bundle/plugin/ModuleBundlesBuildMojo.java create mode 100644 maven-plugins/tags/maven-bundle-plugin-1.0.1/src/main/java/org/apache/tuscany/maven/bundle/plugin/OSGIArtifactVersion.java create mode 100644 maven-plugins/tags/maven-bundle-plugin-1.0.1/src/main/java/org/apache/tuscany/maven/bundle/plugin/ThirdPartyBundleBuildMojo.java (limited to 'maven-plugins/tags/maven-bundle-plugin-1.0.1/src/main/java/org/apache/tuscany/maven/bundle') diff --git a/maven-plugins/tags/maven-bundle-plugin-1.0.1/src/main/java/org/apache/tuscany/maven/bundle/plugin/ArtifactAggregation.java b/maven-plugins/tags/maven-bundle-plugin-1.0.1/src/main/java/org/apache/tuscany/maven/bundle/plugin/ArtifactAggregation.java new file mode 100644 index 0000000000..c5cadd0c4f --- /dev/null +++ b/maven-plugins/tags/maven-bundle-plugin-1.0.1/src/main/java/org/apache/tuscany/maven/bundle/plugin/ArtifactAggregation.java @@ -0,0 +1,73 @@ +/* + * 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 java.util.ArrayList; +import java.util.List; + +import org.apache.maven.artifact.Artifact; + + +public class ArtifactAggregation { + private String symbolicName; + private String version; + private List artifactMembers = new ArrayList(); + private transient List artifacts = new ArrayList(); + + public List getArtifacts() { + return artifacts; + } + + public String getSymbolicName() { + return symbolicName; + } + + public void setSymbolicName(String symbolicName) { + this.symbolicName = symbolicName; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public List getArtifactMembers() { + return artifactMembers; + } + + public void setArtifactMembers(List artifacts) { + this.artifactMembers = artifacts; + } + + public String toString() { + return symbolicName + ";version=\"" + version + "\"\n" + artifactMembers; + } + + public boolean matches(Artifact artifact) { + for(ArtifactMember m: artifactMembers) { + if(m.matches(artifact)) { + return true; + } + } + return false; + } +} \ No newline at end of file diff --git a/maven-plugins/tags/maven-bundle-plugin-1.0.1/src/main/java/org/apache/tuscany/maven/bundle/plugin/ArtifactMember.java b/maven-plugins/tags/maven-bundle-plugin-1.0.1/src/main/java/org/apache/tuscany/maven/bundle/plugin/ArtifactMember.java new file mode 100644 index 0000000000..834ee7825e --- /dev/null +++ b/maven-plugins/tags/maven-bundle-plugin-1.0.1/src/main/java/org/apache/tuscany/maven/bundle/plugin/ArtifactMember.java @@ -0,0 +1,61 @@ +/* + * 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 org.apache.maven.artifact.Artifact; + +public class ArtifactMember { + private String groupId; + private String artifactId; + private String version; + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getArtifactId() { + return artifactId; + } + + public void setArtifactId(String artifactId) { + this.artifactId = artifactId; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String toString() { + return groupId + ":" + artifactId + ":" + version; + } + + public boolean matches(Artifact artifact) { + return groupId.equals(artifact.getGroupId()) && (artifactId == null || artifactId.equals("") + || artifactId.equals("*") || artifactId.equals(artifact.getArtifactId())) + && (version == null || version.equals("") || version.equals("*") || version.equals(artifact.getVersion())); + } +} diff --git a/maven-plugins/tags/maven-bundle-plugin-1.0.1/src/main/java/org/apache/tuscany/maven/bundle/plugin/BundleUtil.java b/maven-plugins/tags/maven-bundle-plugin-1.0.1/src/main/java/org/apache/tuscany/maven/bundle/plugin/BundleUtil.java new file mode 100644 index 0000000000..919b465d09 --- /dev/null +++ b/maven-plugins/tags/maven-bundle-plugin-1.0.1/src/main/java/org/apache/tuscany/maven/bundle/plugin/BundleUtil.java @@ -0,0 +1,408 @@ +/* + * 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.osgi.framework.Constants.BUNDLE_CLASSPATH; +import static org.osgi.framework.Constants.BUNDLE_MANIFESTVERSION; +import static org.osgi.framework.Constants.BUNDLE_NAME; +import static org.osgi.framework.Constants.BUNDLE_SYMBOLICNAME; +import static org.osgi.framework.Constants.BUNDLE_VERSION; +import static org.osgi.framework.Constants.DYNAMICIMPORT_PACKAGE; +import static org.osgi.framework.Constants.EXPORT_PACKAGE; +import static org.osgi.framework.Constants.IMPORT_PACKAGE; + +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.HashSet; +import java.util.Set; +import java.util.jar.Attributes; +import java.util.jar.JarFile; +import java.util.jar.Manifest; +import java.util.logging.Logger; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import org.apache.maven.artifact.versioning.ArtifactVersion; +import org.osgi.framework.Version; + +/** + * Common functions used by the plugin. + * + * @version $Rev$ $Date$ + */ +final class BundleUtil { + private final static Logger logger = Logger.getLogger(BundleUtil.class.getName()); + /** + * Returns the name of a bundle, or null if the given file is not a bundle. + * + * @param file + * @return + * @throws IOException + */ + static String getBundleSymbolicName(File file) throws IOException { + if (!file.exists()) { + return null; + } + String bundleName = null; + if (file.isDirectory()) { + File mf = new File(file, "META-INF/MANIFEST.MF"); + if (mf.isFile()) { + Manifest manifest = new Manifest(new FileInputStream(mf)); + bundleName = manifest.getMainAttributes().getValue(BUNDLE_SYMBOLICNAME); + } + } else { + JarFile jar = new JarFile(file, false); + Manifest manifest = jar.getManifest(); + if (manifest != null){ + bundleName = manifest.getMainAttributes().getValue(BUNDLE_SYMBOLICNAME); + } + jar.close(); + } + if (bundleName == null) { + return bundleName; + } + int sc = bundleName.indexOf(';'); + if (sc != -1) { + bundleName = bundleName.substring(0, sc); + } + return bundleName; + } + + /** + * Generate a Bundle manifest for a set of JAR files. + * + * @param jarFiles + * @param name + * @param symbolicName + * @param version + * @param dir + * @return + * @throws IllegalStateException + */ + static Manifest libraryManifest(Set jarFiles, String name, String symbolicName, String version, String dir) + throws IllegalStateException { + return libraryManifest(jarFiles, name, symbolicName, version, dir, null); + } + /** + * Generate a Bundle manifest for a set of JAR files. + * + * @param jarFiles + * @param name + * @param symbolicName + * @param version + * @param dir + * @param buddyPolicy + * @return + * @throws IllegalStateException + */ + static Manifest libraryManifest(Set jarFiles, String name, String symbolicName, String version, String dir, String buddyPolicy) + throws IllegalStateException { + try { + + // List exported packages and bundle classpath entries + StringBuffer classpath = new StringBuffer(); + Set exportedPackages = new HashSet(); + for (File jarFile : jarFiles) { + addPackages(jarFile, exportedPackages, version); + if (dir != null) { + classpath.append(dir).append("/"); + } + classpath.append(jarFile.getName()); + classpath.append(","); + } + + // Generate export-package and import-package declarations + StringBuffer exports = new StringBuffer(); + StringBuffer imports = new StringBuffer(); + Set pkgs = new HashSet(); + for (String export : exportedPackages) { + String packageName = packageName(export); + if (!pkgs.contains(packageName)) { + // Add corresponding import declaration +// imports.append(export); +// imports.append(','); + pkgs.add(packageName); + exports.append(export); + exports.append(','); + } else { + logger.warning("Duplicate package skipped: " + export); + } + } + + // Create a manifest + Manifest manifest = new Manifest(); + Attributes attributes = manifest.getMainAttributes(); + attributes.putValue("Manifest-Version", "1.0"); + attributes.putValue(BUNDLE_MANIFESTVERSION, "2"); + attributes.putValue(BUNDLE_SYMBOLICNAME, symbolicName); + attributes.putValue(BUNDLE_NAME, name); + attributes.putValue(BUNDLE_VERSION, version); + attributes.putValue(DYNAMICIMPORT_PACKAGE, "*"); + if (buddyPolicy != null && buddyPolicy.length() > 0){ + attributes.putValue("Eclipse-BuddyPolicy", buddyPolicy); + } + if (exports.length() > 1) { + attributes.putValue(EXPORT_PACKAGE, exports.substring(0, exports.length() - 1)); + } + if (imports.length() > 1) { + attributes.putValue(IMPORT_PACKAGE, imports.substring(0, imports.length() - 1)); + } + if (classpath.length() > 1) { + attributes.putValue(BUNDLE_CLASSPATH, classpath.substring(0, classpath.length() - 1)); + } + + return manifest; + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + /** + * Write a bundle manifest. + * + * @param manifest + * @param out + * @throws IOException + */ + static void write(Manifest manifest, OutputStream out) throws IOException { + DataOutputStream dos = new DataOutputStream(out); + Attributes attributes = manifest.getMainAttributes(); + write(attributes, "Manifest-Version", dos); + write(attributes, BUNDLE_MANIFESTVERSION, dos); + write(attributes, BUNDLE_SYMBOLICNAME, dos); + write(attributes, BUNDLE_NAME, dos); + write(attributes, BUNDLE_VERSION, dos); + write(attributes, DYNAMICIMPORT_PACKAGE, dos); + write(attributes, BUNDLE_CLASSPATH, dos); + write(attributes, IMPORT_PACKAGE, dos); + write(attributes, EXPORT_PACKAGE, dos); + write(attributes, "Eclipse-BuddyPolicy", dos); + dos.flush(); + } + + /** + * Add packages to be exported out of a JAR file. + * + * @param jarFile + * @param packages + * @throws IOException + */ + private static void addPackages(File jarFile, Set packages, String version) throws IOException { + if (getBundleSymbolicName(jarFile) == null) { + String ver = ";version=" + version; + addAllPackages(jarFile, packages, ver); + } else { + addExportedPackages(jarFile, packages); + } + } + + /** + * Write manifest attributes. + * + * @param attributes + * @param key + * @param dos + * @throws IOException + */ + private static void write(Attributes attributes, String key, DataOutputStream dos) throws IOException { + String value = attributes.getValue(key); + if (value == null) { + return; + } + StringBuffer line = new StringBuffer(); + line.append(key); + line.append(": "); + line.append(new String(value.getBytes("UTF8"))); + line.append("\r\n"); + int l = line.length(); + if (l > 72) { + for (int i = 70; i < l - 2;) { + line.insert(i, "\r\n "); + i += 72; + l += 3; + } + } + dos.writeBytes(line.toString()); + } + + /** + * Strip an OSGi export, only retain the package name and version. + * + * @param export + * @return + */ + private static String stripExport(String export) { + int sc = export.indexOf(';'); + if (sc == -1) { + return export; + } + String base = export.substring(0, sc); + int v = export.indexOf("version="); + if (v != -1) { + sc = export.indexOf(';', v + 1); + if (sc != -1) { + return base + ";" + export.substring(v, sc); + } else { + return base + ";" + export.substring(v); + } + } else { + return base; + } + } + + /** + * Add all the packages out of a JAR. + * + * @param jarFile + * @param packages + * @param version + * @throws IOException + */ + private static void addAllPackages(File jarFile, Set packages, String version) throws IOException { + ZipInputStream is = new ZipInputStream(new FileInputStream(jarFile)); + ZipEntry entry; + while ((entry = is.getNextEntry()) != null) { + String entryName = entry.getName(); + if (!entry.isDirectory() && entryName != null + && entryName.length() > 0 + && !entryName.startsWith(".") + && entryName.endsWith(".class") // Exclude resources from Export-Package + && entryName.lastIndexOf("/") > 0 + && Character.isJavaIdentifierStart(entryName.charAt(0))) { + String pkg = entryName.substring(0, entryName.lastIndexOf("/")).replace('/', '.'); + if (!pkg.endsWith(".enum")) { + packages.add(pkg + version); + } + } + } + is.close(); + } + + /** + * Returns the name of the exported package in the given export. + * @param export + * @return + */ + private static String packageName(String export) { + int sc = export.indexOf(';'); + if (sc != -1) { + export = export.substring(0, sc); + } + return export; + } + + /** + * Add the packages exported by a bundle. + * + * @param file + * @param packages + * @return + * @throws IOException + */ + private static void addExportedPackages(File file, Set packages) throws IOException { + if (!file.exists()) { + return; + } + + // Read the export-package declaration and get a list of the packages available in a JAR + Set existingPackages = null; + String exports = null; + if (file.isDirectory()) { + File mf = new File(file, "META-INF/MANIFEST.MF"); + if (mf.isFile()) { + Manifest manifest = new Manifest(new FileInputStream(mf)); + exports = manifest.getMainAttributes().getValue(EXPORT_PACKAGE); + } + } else { + JarFile jar = new JarFile(file, false); + Manifest manifest = jar.getManifest(); + exports = manifest.getMainAttributes().getValue(EXPORT_PACKAGE); + jar.close(); + existingPackages = new HashSet(); + addAllPackages(file, existingPackages, ""); + } + if (exports == null) { + return; + } + + // Parse the export-package declaration, and extract the individual packages + StringBuffer buffer = new StringBuffer(); + boolean q = false; + for (int i = 0, n = exports.length(); i < n; i++) { + char c = exports.charAt(i); + if (c == '\"') { + q = !q; + } + if (!q) { + if (c == ',') { + + // Add the exported package to the set, after making sure it really exists in + // the JAR + String export = buffer.toString(); + if (existingPackages == null || existingPackages.contains(packageName(export))) { + packages.add(stripExport(export)); + } + buffer = new StringBuffer(); + continue; + } + } + buffer.append(c); + } + if (buffer.length() != 0) { + + // Add the exported package to the set, after making sure it really exists in + // the JAR + String export = buffer.toString(); + if (existingPackages == null || existingPackages.contains(packageName(export))) { + packages.add(stripExport(export)); + } + } + } + + /** + * Convert the maven version into OSGi version + * @param mavenVersion + * @return + */ + static String osgiVersion(String mavenVersion) { + ArtifactVersion ver = new OSGIArtifactVersion(mavenVersion); + String qualifer = ver.getQualifier(); + if (qualifer != null) { + StringBuffer buf = new StringBuffer(qualifer); + for (int i = 0; i < buf.length(); i++) { + char c = buf.charAt(i); + if (Character.isLetterOrDigit(c) || c == '-' || c == '_') { + // Keep as-is + } else { + buf.setCharAt(i, '_'); + } + } + qualifer = buf.toString(); + } + Version osgiVersion = + new Version(ver.getMajorVersion(), ver.getMinorVersion(), ver.getIncrementalVersion(), qualifer); + String version = osgiVersion.toString(); + return version; + } + +} diff --git a/maven-plugins/tags/maven-bundle-plugin-1.0.1/src/main/java/org/apache/tuscany/maven/bundle/plugin/ModuleBundlesBuildMojo.java b/maven-plugins/tags/maven-bundle-plugin-1.0.1/src/main/java/org/apache/tuscany/maven/bundle/plugin/ModuleBundlesBuildMojo.java new file mode 100644 index 0000000000..f7eff045a8 --- /dev/null +++ b/maven-plugins/tags/maven-bundle-plugin-1.0.1/src/main/java/org/apache/tuscany/maven/bundle/plugin/ModuleBundlesBuildMojo.java @@ -0,0 +1,834 @@ +/* + * 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.BundleUtil.write; + +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.io.PrintStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +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.JarOutputStream; +import java.util.jar.Manifest; +import java.util.zip.ZipEntry; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.ArtifactUtils; +import org.apache.maven.artifact.metadata.ArtifactMetadataSource; +import org.apache.maven.artifact.resolver.ArtifactNotFoundException; +import org.apache.maven.artifact.resolver.ArtifactResolutionException; +import org.apache.maven.artifact.resolver.ArtifactResolutionResult; +import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.logging.Log; +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; + +/** + * A maven plugin that generates a modules directory containing OSGi bundles for all the project's module dependencies. + * + * @version $Rev$ $Date$ + * @goal generate-modules + * @phase generate-resources + * @requiresDependencyResolution test + * @description Generate a modules directory containing OSGi bundles for all the project's module dependencies. + */ +public class ModuleBundlesBuildMojo extends AbstractMojo { + + /** + * The project to create a distribution for. + * + * @parameter expression="${project}" + * @required + * @readonly + */ + private MavenProject project; + + /** + * Project builder -- builds a model from a pom.xml + * + * @component role="org.apache.maven.project.MavenProjectBuilder" + * @required + * @readonly + */ + private MavenProjectBuilder mavenProjectBuilder; + /** + * Used to look up Artifacts in the remote repository. + * + * @component + */ + private org.apache.maven.artifact.factory.ArtifactFactory factory; + + /** + * Used to look up Artifacts in the remote repository. + * + * @component + */ + private org.apache.maven.artifact.resolver.ArtifactResolver resolver; + + /** + * @component role="org.apache.maven.artifact.metadata.ArtifactMetadataSource" + * hint="maven" + * @required + * @readonly + */ + private ArtifactMetadataSource artifactMetadataSource; + + /** + * Location of the local repository. + * + * @parameter expression="${localRepository}" + * @readonly + * @required + */ + private org.apache.maven.artifact.repository.ArtifactRepository local; + + /** + * List of Remote Repositories used by the resolver + * + * @parameter expression="${project.remoteArtifactRepositories}" + * @readonly + * @required + */ + private java.util.List remoteRepos; + + /** + * Target directory. + * + * @parameter expression="${project.build.directory}/modules" + */ + private File targetDirectory; + + /** + * @parameter default-value="features" + */ + private String featuresName = "features"; + + /** + * Directories containing artifacts to exclude. + * + * @parameter + */ + private File[] excludeDirectories; + + /** + * Directories containing groupids to exclude. + * + * @parameter + */ + private String[] excludeGroupIds; + + /** + * Directories containing groupids to include. + * + * @parameter + */ + private String[] includeGroupIds; + + /** + * Set to true to generate configurations under a folder named as the distro + * + * @parameter default-value="true" + */ + private boolean useDistributionName = true; + + /** + * Set to true to generate a PDE target platform configuration. + * + * @parameter default-value="true" + */ + private boolean generateTargetPlatform = true; + + /** + * OSGi execution environment + */ + private String executionEnvironment; + + /** + * A list of Eclipse features to be added to the target definition + * @parameter + */ + private String[] eclipseFeatures; + + /** + * If we use the running eclipse as the default location for the target + * @parameter default-value="true" + */ + private boolean useDefaultLocation = true; + + /** + * Set to true to generate a plugin.xml. + * + * @parameter default-value="false" + */ + private boolean generatePlugin; + + /** + * Generate a configuration/config.ini for equinox + * @parameter default-value="true" + */ + private boolean generateConfig = true; + + /** + * @parameter default-value="true" + */ + private boolean generateBundleStart = true; + + /** + * Generete manifest.jar + * @parameter default-value="true" + */ + private boolean generateManifestJar = true; + + /** + * @parameter default-value="tuscany-sca-manifest.jar" + */ + private String manifestJarName = "tuscany-sca-manifest.jar"; + + /** + * @parameter default-value="tuscany-sca-equinox-manifest.jar" + */ + private String equinoxManifestJarName = "tuscany-sca-equinox-manifest.jar"; + + + /** + * @parameter default-value="true" + */ + private boolean generateAntScript = true; + + /** + * @parameter + */ + private ArtifactAggregation[] artifactAggregations; + + /** + * Inserts a generic Eclipse-BuddyPolicy header into generated artifacts manifests + * @parameter default-value="dependent" + */ + private String genericBuddyPolicy = "dependent"; + + private static final String XML_PI = ""; + private static final String ASL_HEADER = + ""; + + /** + * Group the artifacts by distribution poms + */ + private class ProjectSet { + // Distribution projects + private Map projects; + // Key: the pom artifact id + // Value: the names for the artifacts + private Map> nameMap = new HashMap>(); + + private Map artifactToNameMap = new HashMap(); + + public ProjectSet(List projects) { + super(); + this.projects = new HashMap(); + for (MavenProject p : projects) { + this.projects.put(p.getArtifactId(), p); + } + } + + private MavenProject getProject(String artifactId) { + return projects.get(artifactId); + } + + private void add(Artifact artifact, String name) { + String key = ArtifactUtils.versionlessKey(artifact); + for (MavenProject p : projects.values()) { + Artifact a = (Artifact)p.getArtifactMap().get(key); + if (a != null) { + Set names = nameMap.get(p.getArtifactId()); + if (names == null) { + names = new HashSet(); + nameMap.put(p.getArtifactId(), names); + } + names.add(name); + } + } + artifactToNameMap.put(key, name); + } + } + + public void execute() throws MojoExecutionException { + Log log = getLog(); + + try { + + // Create the target directory + File root; + if (targetDirectory == null) { + root = new File(project.getBuild().getDirectory(), "plugins/"); + } else { + root = targetDirectory; + } + root.mkdirs(); + + // Build sets of exclude directories and included/excluded/groupids + Set excludedFileNames = new HashSet(); + if (excludeDirectories != null) { + for (File f : excludeDirectories) { + if (f.isDirectory()) { + for (String n : f.list()) { + excludedFileNames.add(n); + } + } + } + } + Set includedGroupIds = new HashSet(); + if (includeGroupIds != null) { + for (String g : includeGroupIds) { + includedGroupIds.add(g); + } + } + Set excludedGroupIds = new HashSet(); + if (excludeGroupIds != null) { + for (String g : excludeGroupIds) { + excludedGroupIds.add(g); + } + } + + // Find all the distribution poms + List poms = new ArrayList(); + poms.add(project); + if (useDistributionName) { + for (Object o : project.getArtifacts()) { + Artifact artifact = (Artifact)o; + if ("pom".equals(artifact.getType()) && artifact.getGroupId().equals(project.getGroupId()) + && artifact.getArtifactId().startsWith("tuscany-feature-")) { + log.info("Dependent distribution: " + artifact); + MavenProject pomProject = buildProject(artifact); + poms.add(pomProject); + // log.info(pomProject.getArtifactMap().toString()); + } + } + } + + // Process all the dependency artifacts + ProjectSet bundleSymbolicNames = new ProjectSet(poms); + ProjectSet bundleLocations = new ProjectSet(poms); + ProjectSet jarNames = new ProjectSet(poms); + for (Object o : project.getArtifacts()) { + Artifact artifact = (Artifact)o; + + // Only consider Compile and Runtime dependencies + if (!(Artifact.SCOPE_COMPILE.equals(artifact.getScope()) || Artifact.SCOPE_RUNTIME.equals(artifact + .getScope()) + || Artifact.SCOPE_PROVIDED.equals(artifact.getScope()) || (generateTargetPlatform && Artifact.SCOPE_TEST + .equals(artifact.getScope())))) { + log.info("Skipping artifact: " + artifact); + continue; + } + + // Only consider JAR and WAR files + if (!"jar".equals(artifact.getType()) && !"war".equals(artifact.getType())) { + continue; + } + + // Exclude artifact if its groupId is excluded or if it's not included + if (excludedGroupIds.contains(artifact.getGroupId())) { + log.debug("Artifact groupId is excluded: " + artifact); + continue; + } + if (!includedGroupIds.isEmpty()) { + if (!includedGroupIds.contains(artifact.getGroupId())) { + log.debug("Artifact groupId is not included: " + artifact); + continue; + } + } + + File artifactFile = artifact.getFile(); + if (!artifactFile.exists()) { + log.warn("Artifact doesn't exist: " + artifact); + continue; + } + + if (log.isDebugEnabled()) { + log.debug("Processing artifact: " + artifact); + } + + // Get the bundle name if the artifact is an OSGi bundle + String bundleName = null; + try { + bundleName = BundleUtil.getBundleSymbolicName(artifact.getFile()); + } catch (IOException e) { + throw new MojoExecutionException(e.getMessage(), e); + } + + if (bundleName != null) { + + // Exclude artifact if its file name is excluded + if (excludedFileNames.contains(artifactFile.getName())) { + log.debug("Artifact file is excluded: " + artifact); + continue; + } + + // Copy an OSGi bundle as is + log.info("Adding OSGi bundle artifact: " + artifact); + copyFile(artifactFile, root); + bundleSymbolicNames.add(artifact, bundleName); + bundleLocations.add(artifact, artifactFile.getName()); + jarNames.add(artifact, artifactFile.getName()); + + } else if ("war".equals(artifact.getType())) { + + // Exclude artifact if its file name is excluded + if (excludedFileNames.contains(artifactFile.getName())) { + log.debug("Artifact file is excluded: " + artifact); + continue; + } + + // Copy a WAR as is + log.info("Adding WAR artifact: " + artifact); + copyFile(artifactFile, root); + + } else { + + // String version = BundleUtil.osgiVersion(artifact.getVersion()); + // String symbolicName = (artifact.getGroupId() + "." + artifact.getArtifactId()); + // String dirName = symbolicName + "_" + version; + + String dirName = artifactFile.getName().substring(0, artifactFile.getName().length() - 4); + File dir = new File(root, dirName); + + // Exclude artifact if its file name is excluded + if (excludedFileNames.contains(dir.getName())) { + log.debug("Artifact file is excluded: " + artifact); + continue; + } + + if (artifactAggregations != null) { + boolean aggregated = false; + for (ArtifactAggregation group : artifactAggregations) { + if (group.matches(artifact)) { + group.getArtifacts().add(artifact); + aggregated = true; + break; + } + } + if (aggregated) { + continue; + } + } + + // Create a bundle directory for a non-OSGi JAR + log.info("Adding JAR artifact: " + artifact); + String version = BundleUtil.osgiVersion(artifact.getVersion()); + + Set jarFiles = new HashSet(); + jarFiles.add(artifactFile); + String symbolicName = (artifact.getGroupId() + "." + artifact.getArtifactId()); + Manifest mf = BundleUtil.libraryManifest(jarFiles, symbolicName, symbolicName, version, null, this.genericBuddyPolicy); + File file = new File(dir, "META-INF"); + file.mkdirs(); + file = new File(file, "MANIFEST.MF"); + + FileOutputStream fos = new FileOutputStream(file); + write(mf, fos); + fos.close(); + copyFile(artifactFile, dir); + bundleSymbolicNames.add(artifact, symbolicName); + bundleLocations.add(artifact, dir.getName()); + jarNames.add(artifact, dirName + "/" + artifactFile.getName()); + } + } + + if (artifactAggregations != null) { + for (ArtifactAggregation group : artifactAggregations) { + if (group.getArtifacts().isEmpty()) { + continue; + } + String symbolicName = group.getSymbolicName(); + String version = group.getVersion(); + File dir = new File(root, symbolicName + "-" + version); + dir.mkdir(); + Set jarFiles = new HashSet(); + Artifact artifact = null; + for (Artifact a : group.getArtifacts()) { + log.info("Aggragating JAR artifact: " + a); + artifact = a; + jarFiles.add(a.getFile()); + copyFile(a.getFile(), dir); + jarNames.add(a, symbolicName + "-" + version + "/" + a.getFile().getName()); + } + Manifest mf = BundleUtil.libraryManifest(jarFiles, symbolicName, symbolicName, version, null, this.genericBuddyPolicy); + File file = new File(dir, "META-INF"); + file.mkdirs(); + file = new File(file, "MANIFEST.MF"); + + FileOutputStream fos = new FileOutputStream(file); + write(mf, fos); + fos.close(); + bundleSymbolicNames.add(artifact, symbolicName); + bundleLocations.add(artifact, dir.getName()); + } + } + + // Generate a PDE target + if (generateTargetPlatform) { + generatePDETarget(bundleSymbolicNames, root, log); + } + + // Generate a plugin.xml referencing the PDE target + if (generatePlugin) { + File pluginxml = new File(project.getBasedir(), "plugin.xml"); + FileOutputStream pluginXMLFile = new FileOutputStream(pluginxml); + writePluginXML(new PrintStream(pluginXMLFile)); + pluginXMLFile.close(); + } + + if (generateConfig) { + generateEquinoxConfig(bundleLocations, root, log); + } + + if (generateManifestJar) { + generateManifestJar(jarNames, root, log); + generateEquinoxLauncherManifestJar(jarNames, root, log); + } + + if (generateAntScript) { + generateANTPath(jarNames, root, log); + } + + } catch (Exception e) { + throw new MojoExecutionException(e.getMessage(), e); + } + + } + + private void generateANTPath(ProjectSet jarNames, File root, Log log) throws FileNotFoundException, IOException { + for (Map.Entry> e : jarNames.nameMap.entrySet()) { + Set jars = e.getValue(); + File feature = new File(root, "../" + featuresName + "/" + (useDistributionName ? trim(e.getKey()) : "")); + feature.mkdirs(); + File antPath = new File(feature, "build-path.xml"); + log.info("Generating ANT build path: " + antPath.getCanonicalPath()); + FileOutputStream fos = new FileOutputStream(antPath); + PrintStream ps = new PrintStream(fos); + // ps.println(XML_PI); + ps.println(ASL_HEADER); + String name = trim(e.getKey()); + ps.println(""); + ps.println(" "); + ps.println(" "); + ps.println(" "); + ps.println(" "); + for (String jar : jars) { + ps.println(" "); + } + ps.println(" "); + ps.println(" "); + ps.println(""); + } + } + + private void generateManifestJar(ProjectSet jarNames, File root, Log log) throws FileNotFoundException, IOException { + for (Map.Entry> e : jarNames.nameMap.entrySet()) { + MavenProject pom = jarNames.getProject(e.getKey()); + Set jars = e.getValue(); + File feature = new File(root, "../" + featuresName + "/" + (useDistributionName ? trim(e.getKey()) : "")); + feature.mkdirs(); + File mfJar = new File(feature, manifestJarName); + log.info("Generating manifest jar: " + mfJar.getCanonicalPath()); + FileOutputStream fos = new FileOutputStream(mfJar); + Manifest mf = new Manifest(); + StringBuffer cp = new StringBuffer(); + String path = (useDistributionName ? "../../" : "../") + root.getName(); + for (String jar : jars) { + cp.append(path).append('/').append(jar).append(' '); + } + if (cp.length() > 0) { + cp.deleteCharAt(cp.length() - 1); + } + Attributes attrs = mf.getMainAttributes(); + attrs.putValue("Manifest-Version", "1.0"); + attrs.putValue("Implementation-Title", pom.getName()); + attrs.putValue("Implementation-Vendor", "The Apache Software Foundation"); + attrs.putValue("Implementation-Vendor-Id", "org.apache"); + attrs.putValue("Implementation-Version", pom.getVersion()); + attrs.putValue("Class-Path", cp.toString()); + attrs.putValue("Main-Class", "org.apache.tuscany.sca.node.launcher.NodeMain"); + JarOutputStream jos = new JarOutputStream(fos, mf); + addFileToJar(jos, "META-INF/LICENSE", getClass().getResource("LICENSE.txt")); + addFileToJar(jos, "META-INF/NOTICE", getClass().getResource("NOTICE.txt")); + jos.close(); + } + } + + private void generateEquinoxLauncherManifestJar(ProjectSet jarNames, File root, Log log) throws Exception { + String equinoxLauncher = "org.apache.tuscany.sca:tuscany-node-launcher-equinox"; + Artifact artifact = (Artifact)project.getArtifactMap().get(equinoxLauncher); + if (artifact == null) { + return; + } + Set artifacts = resolveTransitively(artifact).getArtifacts(); + File feature = new File(root, "../" + featuresName + "/"); + feature.mkdirs(); + File mfJar = new File(feature, equinoxManifestJarName); + log.info("Generating equinox manifest jar: " + mfJar.getCanonicalPath()); + FileOutputStream fos = new FileOutputStream(mfJar); + Manifest mf = new Manifest(); + StringBuffer cp = new StringBuffer(); + String path = "../" + root.getName(); + + for (Object o : artifacts) { + Artifact a = (Artifact)o; + if (!Artifact.SCOPE_TEST.equals(a.getScope())) { + String id = ArtifactUtils.versionlessKey(a); + String jar = jarNames.artifactToNameMap.get(id); + if (jar != null) { + cp.append(path).append('/').append(jar).append(' '); + } + } + } + if (cp.length() > 0) { + cp.deleteCharAt(cp.length() - 1); + } + Attributes attrs = mf.getMainAttributes(); + attrs.putValue("Manifest-Version", "1.0"); + attrs.putValue("Implementation-Title", artifact.getId()); + attrs.putValue("Implementation-Vendor", "The Apache Software Foundation"); + attrs.putValue("Implementation-Vendor-Id", "org.apache"); + attrs.putValue("Implementation-Version", artifact.getVersion()); + attrs.putValue("Class-Path", cp.toString()); + attrs.putValue("Main-Class", "org.apache.tuscany.sca.node.equinox.launcher.NodeMain"); + JarOutputStream jos = new JarOutputStream(fos, mf); + addFileToJar(jos, "META-INF/LICENSE", getClass().getResource("LICENSE.txt")); + addFileToJar(jos, "META-INF/NOTICE", getClass().getResource("NOTICE.txt")); + jos.close(); + } + + private void generateEquinoxConfig(ProjectSet bundleLocations, File root, Log log) throws IOException { + for (Map.Entry> e : bundleLocations.nameMap.entrySet()) { + Set locations = e.getValue(); + File feature = new File(root, "../" + featuresName + "/" + (useDistributionName ? trim(e.getKey()) : "")); + File config = new File(feature, "configuration"); + config.mkdirs(); + File ini = new File(config, "config.ini"); + log.info("Generating configuation: " + ini.getCanonicalPath()); + FileOutputStream fos = new FileOutputStream(ini); + PrintStream ps = new PrintStream(fos); + ps.print("osgi.bundles="); + for (String f : locations) { + ps.print(f); + if (generateBundleStart) { + ps.print("@:start,"); + } else { + ps.println(","); + } + } + ps.println(); + ps.println("eclipse.ignoreApp=true"); + // Do not shutdown + ps.println("osgi.noShutdown=true"); + // Start a default console + ps.println("osgi.console="); + ps.close(); + } + } + + private void generatePDETarget(ProjectSet bundleSymbolicNames, File root, Log log) throws FileNotFoundException, + IOException { + for (Map.Entry> e : bundleSymbolicNames.nameMap.entrySet()) { + Set bundles = e.getValue(); + String name = trim(e.getKey()); + File feature = new File(root, "../" + featuresName + "/" + (useDistributionName ? name : "")); + feature.mkdirs(); + File target = new File(feature, "tuscany.target"); + log.info("Generating target definition: " + target.getCanonicalPath()); + FileOutputStream targetFile = new FileOutputStream(target); + if (!bundles.contains("org.eclipse.osgi")) { + bundles.add("org.eclipse.osgi"); + } + writeTarget(new PrintStream(targetFile), name, bundles, eclipseFeatures); + targetFile.close(); + } + } + + private MavenProject buildProject(Artifact artifact) throws ProjectBuildingException, + InvalidDependencyVersionException, ArtifactResolutionException, ArtifactNotFoundException { + MavenProject pomProject = + mavenProjectBuilder.buildFromRepository(artifact, this.remoteRepos, this.local); + if (pomProject.getDependencyArtifacts() == null) { + pomProject.setDependencyArtifacts(pomProject + .createArtifacts(factory, + null, // Artifact.SCOPE_TEST, + new ScopeArtifactFilter(Artifact.SCOPE_TEST))); + } + ArtifactResolutionResult result = + resolver.resolveTransitively(pomProject.getDependencyArtifacts(), + pomProject.getArtifact(), + remoteRepos, + local, + artifactMetadataSource); + pomProject.setArtifacts(result.getArtifacts()); + return pomProject; + } + + private ArtifactResolutionResult resolveTransitively(Artifact artifact) throws ArtifactResolutionException, ArtifactNotFoundException { + Artifact originatingArtifact = factory.createBuildArtifact("dummy", "dummy", "1.0", "jar"); + + return resolver.resolveTransitively(Collections.singleton(artifact), + originatingArtifact, + local, + remoteRepos, + artifactMetadataSource, + null); + } + + /** + * Convert tuscany-feature-xyz to feature-xyz + * @param artifactId + * @return + */ + private String trim(String artifactId) { + if (artifactId.startsWith("tuscany-feature-")) { + return artifactId.substring("tuscany-feature-".length()); + } else { + return artifactId; + } + } + + private static void copyFile(File jar, File dir) throws FileNotFoundException, IOException { + byte[] buf = new byte[4096]; + File jarFile = new File(dir, jar.getName()); + FileInputStream in = new FileInputStream(jar); + FileOutputStream out = new FileOutputStream(jarFile); + for (;;) { + int len = in.read(buf); + if (len > 0) { + out.write(buf, 0, len); + } else { + break; + } + } + in.close(); + out.close(); + } + + private static void addFileToJar(JarOutputStream out, String entryName, URL file) throws FileNotFoundException, IOException { + byte[] buf = new byte[4096]; + InputStream in = file.openStream(); + out.putNextEntry(new ZipEntry(entryName)); + for (;;) { + int len = in.read(buf); + if (len > 0) { + out.write(buf, 0, len); + } else { + break; + } + } + in.close(); + out.closeEntry(); + } + + private void writeTarget(PrintStream ps, String pom, Set ids, String[] features) { + ps.println(XML_PI); + ps.println(""); + ps.println(ASL_HEADER); + + ps.println(""); + + if (executionEnvironment != null) { + ps.println(" "); + ps.println(" " + executionEnvironment + ""); + ps.println(" "); + } + + if (useDefaultLocation) { + ps.println(" "); + } else { + ps.println(" "); + } + + // ps.println(""); + ps.println(" "); + ps.println(" "); + for (String id : ids) { + ps.println(" "); + } + ps.println(" "); + ps.println(" "); + if (features != null) { + for (String f : features) { + ps.println(" "); + } + } + ps.println(" "); + if (useDefaultLocation) { + ps.println(" "); + // Not sure why the extra path needs to the plugins folder + ps.println(" "); + ps.println(" "); + } + ps.println(" "); + + ps.println(""); + + } + + private static void writePluginXML(PrintStream ps) { + ps.println(XML_PI); + ps.println(""); + ps.println(ASL_HEADER); + ps.println(""); + ps.println(""); + ps.println(""); + ps.println(""); + ps.println(""); + } +} diff --git a/maven-plugins/tags/maven-bundle-plugin-1.0.1/src/main/java/org/apache/tuscany/maven/bundle/plugin/OSGIArtifactVersion.java b/maven-plugins/tags/maven-bundle-plugin-1.0.1/src/main/java/org/apache/tuscany/maven/bundle/plugin/OSGIArtifactVersion.java new file mode 100644 index 0000000000..7c6e72e049 --- /dev/null +++ b/maven-plugins/tags/maven-bundle-plugin-1.0.1/src/main/java/org/apache/tuscany/maven/bundle/plugin/OSGIArtifactVersion.java @@ -0,0 +1,232 @@ +package org.apache.tuscany.maven.bundle.plugin; + +/* + * 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. + */ + +import java.util.StringTokenizer; + +import org.apache.maven.artifact.versioning.ArtifactVersion; + +public class OSGIArtifactVersion implements ArtifactVersion { + private Integer buildNumber; + + private Integer incrementalVersion; + + private Integer majorVersion; + + private Integer minorVersion; + + private String qualifier; + + private String unparsed; + + public OSGIArtifactVersion(String version) { + parseVersion(version); + } + + public int compareTo(Object o) { + ArtifactVersion otherVersion = (ArtifactVersion) o; + + int result = getMajorVersion() - otherVersion.getMajorVersion(); + if (result == 0) { + result = getMinorVersion() - otherVersion.getMinorVersion(); + } + if (result == 0) { + result = getIncrementalVersion() - otherVersion.getIncrementalVersion(); + } + if (result == 0) { + if (this.qualifier != null) { + String otherQualifier = otherVersion.getQualifier(); + + if (otherQualifier != null) { + if ((this.qualifier.length() > otherQualifier.length()) + && this.qualifier.startsWith(otherQualifier)) { + // here, the longer one that otherwise match is + // considered older + result = -1; + } + else if ((this.qualifier.length() < otherQualifier.length()) + && otherQualifier.startsWith(this.qualifier)) { + // here, the longer one that otherwise match is + // considered older + result = 1; + } + else { + result = this.qualifier.compareTo(otherQualifier); + } + } + else { + // otherVersion has no qualifier but we do - that's newer + result = -1; + } + } + else if (otherVersion.getQualifier() != null) { + // otherVersion has a qualifier but we don't, we're newer + result = 1; + } + else { + result = getBuildNumber() - otherVersion.getBuildNumber(); + } + } + return result; + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + + if (false == (other instanceof ArtifactVersion)) { + return false; + } + + return 0 == compareTo(other); + } + + public int getBuildNumber() { + return this.buildNumber != null ? this.buildNumber.intValue() : 0; + } + + public int getIncrementalVersion() { + return this.incrementalVersion != null ? this.incrementalVersion.intValue() : 0; + } + + public int getMajorVersion() { + return this.majorVersion != null ? this.majorVersion.intValue() : 0; + } + + public int getMinorVersion() { + return this.minorVersion != null ? this.minorVersion.intValue() : 0; + } + + public String getQualifier() { + return this.qualifier; + } + + @Override + public int hashCode() { + int result = 1229; + + result = 1223 * result + getMajorVersion(); + result = 1223 * result + getMinorVersion(); + result = 1223 * result + getIncrementalVersion(); + result = 1223 * result + getBuildNumber(); + + if (null != getQualifier()) { + result = 1223 * result + getQualifier().hashCode(); + } + + return result; + } + + public final void parseVersion(String version) { + this.unparsed = version; + + int index = version.indexOf("-"); + + String part1; + String part2 = null; + + if (index < 0) { + part1 = version; + } + else { + part1 = version.substring(0, index); + part2 = version.substring(index + 1); + } + + if (part2 != null) { + try { + if ((part2.length() == 1) || !part2.startsWith("0")) { + this.buildNumber = Integer.valueOf(part2); + } + else { + this.qualifier = part2; + } + } + catch (NumberFormatException e) { + this.qualifier = part2; + } + } + + if ((part1.indexOf(".") < 0) && !part1.startsWith("0")) { + try { + this.majorVersion = Integer.valueOf(part1); + } + catch (NumberFormatException e) { + // qualifier is the whole version, including "-" + this.qualifier = version; + this.buildNumber = null; + } + } + else { + StringTokenizer tok = new StringTokenizer(part1, "."); + + String s; + + if (tok.hasMoreTokens()) { + s = tok.nextToken(); + try { + this.majorVersion = Integer.valueOf(s); + + if (tok.hasMoreTokens()) { + s = tok.nextToken(); + try { + this.minorVersion = Integer.valueOf(s); + if (tok.hasMoreTokens()) { + + s = tok.nextToken(); + try { + this.incrementalVersion = Integer.valueOf(s); + + } + catch (NumberFormatException e) { + this.qualifier = s; + } + } + } + catch (NumberFormatException e) { + this.qualifier = s; + } + } + } + catch (NumberFormatException e) { + this.qualifier = s; + } + } + + if (tok.hasMoreTokens()) { + StringBuffer qualifier = new StringBuffer(this.qualifier != null ? this.qualifier : ""); + qualifier.append(tok.nextToken()); + while (tok.hasMoreTokens()) { + qualifier.append("_"); + qualifier.append(tok.nextToken()); + } + + this.qualifier = qualifier.toString(); + } + + } + } + + @Override + public String toString() { + return this.unparsed; + } +} diff --git a/maven-plugins/tags/maven-bundle-plugin-1.0.1/src/main/java/org/apache/tuscany/maven/bundle/plugin/ThirdPartyBundleBuildMojo.java b/maven-plugins/tags/maven-bundle-plugin-1.0.1/src/main/java/org/apache/tuscany/maven/bundle/plugin/ThirdPartyBundleBuildMojo.java new file mode 100644 index 0000000000..880f1379e0 --- /dev/null +++ b/maven-plugins/tags/maven-bundle-plugin-1.0.1/src/main/java/org/apache/tuscany/maven/bundle/plugin/ThirdPartyBundleBuildMojo.java @@ -0,0 +1,152 @@ +/* + * 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.BundleUtil.write; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; +import java.util.jar.Manifest; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.project.MavenProject; + +/** + * A Maven plugin that builds an OSGi bundle for the project's third-party dependencies. + * + * @version $Rev$ $Date$ + * @goal assemble-thirdparty-bundle + * @phase generate-resources + * @requiresDependencyResolution test + * @description Build an OSGi bundle for the project's third party dependencies + */ +public class ThirdPartyBundleBuildMojo extends AbstractMojo { + + /** + * The project to build the bundle for. + * + * @parameter expression="${project}" + * @required + * @readonly + */ + private MavenProject project; + + /** + * The bundle symbolic name + * + * @parameter + */ + private String symbolicName; + + public void execute() throws MojoExecutionException { + Log log = getLog(); + + String projectGroupId = project.getGroupId(); + Set jarFiles = new HashSet(); + for (Object o : project.getArtifacts()) { + Artifact artifact = (Artifact)o; + + if (!(Artifact.SCOPE_COMPILE.equals(artifact.getScope()) || Artifact.SCOPE_RUNTIME.equals(artifact + .getScope()))) { + if (log.isDebugEnabled()) { + log.debug("Skipping artifact: " + artifact); + } + continue; + } + if (!"jar".equals(artifact.getType())) { + continue; + } + if (projectGroupId.equals(artifact.getGroupId())) { + continue; + } + + if (log.isDebugEnabled()) { + log.debug("Artifact: " + artifact); + } + String bundleName = null; + try { + bundleName = BundleUtil.getBundleSymbolicName(artifact.getFile()); + } catch (IOException e) { + throw new MojoExecutionException(e.getMessage(), e); + } + if (bundleName == null || true) { + if (artifact.getFile().exists()) { + log.info("Adding third party jar: " + artifact); + jarFiles.add(artifact.getFile()); + } else { + log.warn("Third party jar not found: " + artifact); + } + } + } + + try { + String version = BundleUtil.osgiVersion(project.getVersion()); + + Manifest mf = BundleUtil.libraryManifest(jarFiles, project.getName(), symbolicName, version, "lib"); + File file = new File(project.getBasedir(), "META-INF"); + file.mkdir(); + file = new File(file, "MANIFEST.MF"); + if (log.isDebugEnabled()) { + log.debug("Generating " + file); + } + + FileOutputStream fos = new FileOutputStream(file); + write(mf, fos); + fos.close(); + + File lib = new File(project.getBasedir(), "lib"); + if (lib.isDirectory()) { + for (File c : lib.listFiles()) { + c.delete(); + } + } + lib.mkdir(); + byte[] buf = new byte[4096]; + for (File jar : jarFiles) { + File jarFile = new File(lib, jar.getName()); + if (log.isDebugEnabled()) { + log.debug("Copying " + jar + " to " + jarFile); + } + FileInputStream in = new FileInputStream(jar); + FileOutputStream out = new FileOutputStream(jarFile); + for (;;) { + int len = in.read(buf); + if (len > 0) { + out.write(buf, 0, len); + } else { + break; + } + } + in.close(); + out.close(); + } + } catch (Exception e) { + throw new MojoExecutionException(e.getMessage(), e); + } + + } + +} -- cgit v1.2.3