You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tuscany.apache.org by rf...@apache.org on 2008/09/13 01:08:41 UTC

svn commit: r694838 - in /tuscany/java/sca/tools/maven/maven-tuscany-bundle-plugin/src/main/java/org/apache/tuscany/tools/sca/tuscany/bundle/plugin: LibraryBundleMojo.java LibraryBundleUtil.java

Author: rfeng
Date: Fri Sep 12 16:08:40 2008
New Revision: 694838

URL: http://svn.apache.org/viewvc?rev=694838&view=rev
Log:
Add a MOJO to create the 3rd party library bundle manifest

Added:
    tuscany/java/sca/tools/maven/maven-tuscany-bundle-plugin/src/main/java/org/apache/tuscany/tools/sca/tuscany/bundle/plugin/LibraryBundleMojo.java   (with props)
    tuscany/java/sca/tools/maven/maven-tuscany-bundle-plugin/src/main/java/org/apache/tuscany/tools/sca/tuscany/bundle/plugin/LibraryBundleUtil.java   (with props)

Added: tuscany/java/sca/tools/maven/maven-tuscany-bundle-plugin/src/main/java/org/apache/tuscany/tools/sca/tuscany/bundle/plugin/LibraryBundleMojo.java
URL: http://svn.apache.org/viewvc/tuscany/java/sca/tools/maven/maven-tuscany-bundle-plugin/src/main/java/org/apache/tuscany/tools/sca/tuscany/bundle/plugin/LibraryBundleMojo.java?rev=694838&view=auto
==============================================================================
--- tuscany/java/sca/tools/maven/maven-tuscany-bundle-plugin/src/main/java/org/apache/tuscany/tools/sca/tuscany/bundle/plugin/LibraryBundleMojo.java (added)
+++ tuscany/java/sca/tools/maven/maven-tuscany-bundle-plugin/src/main/java/org/apache/tuscany/tools/sca/tuscany/bundle/plugin/LibraryBundleMojo.java Fri Sep 12 16:08:40 2008
@@ -0,0 +1,183 @@
+/*
+ * 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.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+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;
+
+/**
+ * @version $Rev$ $Date$
+ * @goal build
+ * @phase process-sources
+ * @requiresDependencyResolution test
+ * @description Build a virtual bundle for 3rd party dependencies
+ */
+public class LibraryBundleMojo extends AbstractMojo {
+    /**
+     * The project to create a build for.
+     *
+     * @parameter expression="${project}"
+     * @required
+     * @readonly
+     */
+    private MavenProject project;
+
+    /**
+     * The basedir of the project.
+     * 
+     * @parameter expression="${basedir}"
+     * @required @readonly
+     */
+    protected File basedir;
+
+    /**
+     * Used to look up Artifacts in the remote repository.
+     * 
+     * @parameter expression="${component.org.apache.maven.artifact.factory.ArtifactFactory}"
+     * @required
+     * @readonly
+     */
+    protected org.apache.maven.artifact.factory.ArtifactFactory factory;
+
+    /**
+     * Used to look up Artifacts in the remote repository.
+     * 
+     * @parameter expression="${component.org.apache.maven.artifact.resolver.ArtifactResolver}"
+     * @required
+     * @readonly
+     */
+    protected org.apache.maven.artifact.resolver.ArtifactResolver resolver;
+
+    /**
+     * Location of the local repository.
+     * 
+     * @parameter expression="${localRepository}"
+     * @readonly
+     * @required
+     */
+    protected org.apache.maven.artifact.repository.ArtifactRepository local;
+
+    /**
+     * List of Remote Repositories used by the resolver
+     * 
+     * @parameter expression="${project.remoteArtifactRepositories}"
+     * @readonly
+     * @required
+     */
+    protected java.util.List remoteRepos;
+
+    /**
+     * @parameter
+     */
+    protected boolean copyJars = false;
+
+    public void execute() throws MojoExecutionException {
+        if (project.getPackaging().equals("pom")) {
+            return;
+        }
+
+        Log log = getLog();
+        List<File> jarFiles = new ArrayList<File>();
+        for (Object o : project.getArtifacts()) {
+            Artifact a = (Artifact)o;
+            if (!(Artifact.SCOPE_COMPILE.equals(a.getScope()) || Artifact.SCOPE_RUNTIME.equals(a.getScope()))) {
+                if (log.isDebugEnabled()) {
+                    log.debug("Skipping artifact: " + a);
+                }
+                continue;
+            }
+            if (log.isDebugEnabled()) {
+                log.debug("Artifact: " + a);
+            }
+            String bundleName = null;
+            try {
+                bundleName = LibraryBundleUtil.getBundleName(a.getFile());
+            } catch (IOException e) {
+                throw new MojoExecutionException(e.getMessage(), e);
+            }
+            if (bundleName == null) {
+                if (log.isDebugEnabled()) {
+                    log.debug("Adding non-OSGi jar: " + a);
+                }
+                jarFiles.add(a.getFile());
+            }
+        }
+
+        try {
+            String version = project.getVersion();
+            if (version.endsWith(Artifact.SNAPSHOT_VERSION)) {
+                version = version.substring(0, version.length() - Artifact.SNAPSHOT_VERSION.length() - 1);
+            }
+
+            Manifest mf = LibraryBundleUtil.libraryManifest(jarFiles, project.getName(), version, copyJars);
+            File file = new File(project.getBasedir(), "META-INF/MANIFEST.MF");
+            if (log.isDebugEnabled()) {
+                log.debug("Generating " + file);
+            }
+
+            file.mkdirs();
+            FileOutputStream fos = new FileOutputStream(file);
+            mf.write(fos);
+            fos.close();
+
+            if (copyJars) {
+                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);
+                    int len = 0;
+                    while (len > 0) {
+                        len = in.read(buf);
+                        if (len > 0) {
+                            out.write(buf, 0, len);
+                        }
+                    }
+                    in.close();
+                    out.close();
+                }
+            }
+        } catch (Exception e) {
+            throw new MojoExecutionException(e.getMessage(), e);
+        }
+
+    }
+
+}

Propchange: tuscany/java/sca/tools/maven/maven-tuscany-bundle-plugin/src/main/java/org/apache/tuscany/tools/sca/tuscany/bundle/plugin/LibraryBundleMojo.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: tuscany/java/sca/tools/maven/maven-tuscany-bundle-plugin/src/main/java/org/apache/tuscany/tools/sca/tuscany/bundle/plugin/LibraryBundleMojo.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: tuscany/java/sca/tools/maven/maven-tuscany-bundle-plugin/src/main/java/org/apache/tuscany/tools/sca/tuscany/bundle/plugin/LibraryBundleUtil.java
URL: http://svn.apache.org/viewvc/tuscany/java/sca/tools/maven/maven-tuscany-bundle-plugin/src/main/java/org/apache/tuscany/tools/sca/tuscany/bundle/plugin/LibraryBundleUtil.java?rev=694838&view=auto
==============================================================================
--- tuscany/java/sca/tools/maven/maven-tuscany-bundle-plugin/src/main/java/org/apache/tuscany/tools/sca/tuscany/bundle/plugin/LibraryBundleUtil.java (added)
+++ tuscany/java/sca/tools/maven/maven-tuscany-bundle-plugin/src/main/java/org/apache/tuscany/tools/sca/tuscany/bundle/plugin/LibraryBundleUtil.java Fri Sep 12 16:08:40 2008
@@ -0,0 +1,244 @@
+/*
+ * 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 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.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.util.HashSet;
+import java.util.List;
+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.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import org.osgi.framework.Bundle;
+
+/**
+ * Common functions and constants used by the admin components.
+ *
+ * @version $Rev$ $Date$
+ */
+public final class LibraryBundleUtil {
+
+    private static final String LAUNCHER_EQUINOX_LIBRARIES = "org.apache.tuscany.sca.node.launcher.equinox.libraries";
+
+    static File file(URL url) {
+        if (url == null || !url.getProtocol().equals("file")) {
+            return null;
+        } else {
+            String filename = url.getFile().replace('/', File.separatorChar);
+            int pos = 0;
+            while ((pos = filename.indexOf('%', pos)) >= 0) {
+                if (pos + 2 < filename.length()) {
+                    String hexStr = filename.substring(pos + 1, pos + 3);
+                    char ch = (char)Integer.parseInt(hexStr, 16);
+                    filename = filename.substring(0, pos) + ch + filename.substring(pos + 3);
+                }
+            }
+            return new File(filename);
+        }
+    }
+
+    static Pattern pattern = Pattern.compile("-([0-9.]+)");
+
+    private static String version(String jarFile) {
+        Matcher matcher = pattern.matcher(jarFile);
+        String version = "1.0.0";
+        if (matcher.find()) {
+            version = matcher.group();
+            if (version.endsWith(".")) {
+                version = version.substring(1, version.length() - 1);
+            } else {
+                version = version.substring(1);
+            }
+        }
+        return version;
+    }
+
+    private static void addPackages(File jarFile, Set<String> packages) throws IOException {
+        String version = ";version=" + version(jarFile.getPath());
+        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) {
+                String pkg = entryName.substring(0, entryName.lastIndexOf("/")).replace('/', '.') + version;
+                packages.add(pkg);
+            }
+        }
+        is.close();
+    }
+
+    static Manifest libraryManifest(List<File> jarFiles, String name, String version, boolean copyJars)
+        throws IllegalStateException {
+        try {
+
+            // List exported packages and bundle classpath entries
+            StringBuffer classpath = new StringBuffer();
+            StringBuffer exports = new StringBuffer();
+            StringBuffer imports = new StringBuffer();
+            Set<String> packages = new HashSet<String>();
+            for (File jarFile : jarFiles) {
+                addPackages(jarFile, packages);
+                if (copyJars) {
+                    classpath.append("\"lib/");
+                    classpath.append(jarFile.getName());
+                    classpath.append("\",");
+                } else {
+                    classpath.append("\"external:");
+                    classpath.append(jarFile.getPath().replace(File.separatorChar, '/'));
+                    classpath.append("\",");
+                }
+            }
+
+            Set<String> importPackages = new HashSet<String>();
+            for (String pkg : packages) {
+                exports.append(pkg);
+                exports.append(',');
+
+                String importPackage = pkg;
+                int index = pkg.indexOf(';');
+                if (index != -1) {
+                    importPackage = pkg.substring(0, index);
+                }
+                if (!importPackages.contains(importPackage)) {
+                    imports.append(importPackage);
+                    imports.append(',');
+                    importPackages.add(importPackage);
+                }
+            }
+
+            // 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, LAUNCHER_EQUINOX_LIBRARIES);
+            attributes.putValue(BUNDLE_NAME, name);
+            attributes.putValue(BUNDLE_VERSION, version);
+            attributes.putValue(EXPORT_PACKAGE, exports.substring(0, exports.length() - 1));
+            attributes.putValue(IMPORT_PACKAGE, imports.substring(0, imports.length() - 1));
+            attributes.putValue(BUNDLE_CLASSPATH, classpath.substring(0, classpath.length() - 1));
+            attributes.putValue(DYNAMICIMPORT_PACKAGE, "*");
+
+            return manifest;
+        } catch (IOException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    static String dump(Manifest mf) throws IOException {
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        mf.write(bos);
+        return new String(bos.toByteArray());
+    }
+
+    static byte[] generateBundle(Manifest mf) throws IOException {
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        JarOutputStream jos = new JarOutputStream(bos, mf);
+        jos.close();
+        return bos.toByteArray();
+    }
+
+    /**
+     * Returns the name of a bundle, or null if the given file is not a bundle.
+     *  
+     * @param file
+     * @return
+     * @throws IOException
+     */
+    static String getBundleName(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();
+            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;
+    }
+
+    public static String string(Bundle b, boolean verbose) {
+        StringBuffer sb = new StringBuffer();
+        sb.append(b.getBundleId()).append(" ").append(b.getSymbolicName());
+        int s = b.getState();
+        if ((s & Bundle.UNINSTALLED) != 0) {
+            sb.append(" UNINSTALLED");
+        }
+        if ((s & Bundle.INSTALLED) != 0) {
+            sb.append(" INSTALLED");
+        }
+        if ((s & Bundle.RESOLVED) != 0) {
+            sb.append(" RESOLVED");
+        }
+        if ((s & Bundle.STARTING) != 0) {
+            sb.append(" STARTING");
+        }
+        if ((s & Bundle.STOPPING) != 0) {
+            sb.append(" STOPPING");
+        }
+        if ((s & Bundle.ACTIVE) != 0) {
+            sb.append(" ACTIVE");
+        }
+
+        if (verbose) {
+            sb.append(" ").append(b.getLocation());
+            sb.append(" ").append(b.getHeaders());
+        }
+        return sb.toString();
+    }
+}

Propchange: tuscany/java/sca/tools/maven/maven-tuscany-bundle-plugin/src/main/java/org/apache/tuscany/tools/sca/tuscany/bundle/plugin/LibraryBundleUtil.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: tuscany/java/sca/tools/maven/maven-tuscany-bundle-plugin/src/main/java/org/apache/tuscany/tools/sca/tuscany/bundle/plugin/LibraryBundleUtil.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date