Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   * Copyright (c) 2007-2011 Oracle and/or its affiliates. All rights reserved.
   * The contents of this file are subject to the terms of either the GNU
   * General Public License Version 2 only ("GPL") or the Common Development
   * and Distribution License("CDDL") (collectively, the "License").  You
   * may not use this file except in compliance with the License.  You can
  * obtain a copy of the License at
  * or packager/legal/LICENSE.txt.  See the License for the specific
  * language governing permissions and limitations under the License.
  * When distributing the software, include this License Header Notice in each
  * file and include the License file at packager/legal/LICENSE.txt.
  * GPL Classpath Exception:
  * Oracle designates this particular file as subject to the "Classpath"
  * exception as provided by Oracle in the GPL Version 2 section of the License
  * file that accompanied this code.
  * Modifications:
  * If applicable, add the following below the License Header, with the fields
  * enclosed by brackets [] replaced by your own identifying information:
  * "Portions Copyright [year] [name of copyright owner]"
  * Contributor(s):
  * If you wish your version of this file to be governed by only the CDDL or
  * only the GPL Version 2, indicate your decision by adding "[Contributor]
  * elects to include this software in this distribution under the [CDDL or GPL
  * Version 2] license."  If you don't indicate a single choice of license, a
  * recipient has the option to distribute your version of this file under
  * either the CDDL, the GPL Version 2 or to extend the choice of license to
  * its licensees as provided above.  However, if you add GPL Version 2 code
  * and therefore, elected the GPL Version 2 license, then the option applies
  * only if the new code is made subject to such option by the copyright
  * holder.
 package com.sun.enterprise.module.maven;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import static org.osgi.framework.Constants.*;

Prepares OSGi manifest entries in MavenArchiveConfiguration.

 public class OSGiPackager {
      * TODO:
      * 1. Does not yet calculate uses attribute in Export-Package
     private static final Logger logger = Logger.getAnonymousLogger();
     private Properties props;
     public OSGiPackager(Properties props) {
         this. = props;

Reads information from the POM and the artifact archive to configure the OSGi manifest entries. Returns a new set of entries if the archive does not already have manifest entries, else it uses the existing entries map. If any of the attribute already exists, then it skips its processing honoring user's request. It uses the following rules: Bundle-SymbolicName is assumed to be "${groupId}.${artifactId}" Bundle-Version is derived from "${pom.version}" using VersionTranslator.MavenToOSGi(String) Bundle-Description is assumed to be "${pom.description}". Bundle-Vendor is assumed to be "${}". Require-Bundle is populated by values read from pom dependencies Note: There is no support for Export-Package yet. It sets Bundle-ManifestVersion as 2 which indicates OSGi r4 bundle.

pom The Maven project object
archive The archive that is being built
classesDirectory output for javac
Manifest entries
    public Map<String,StringconfigureOSGiManifest(MavenProject pomMavenArchiveConfiguration archiveFile classesDirectorythrows IOException {
            entries = archive.getManifestEntries();
            entries = new HashMap<String,String>();
        if(entries.get(BUNDLE_MANIFESTVERSION) == null) {
            // 2 indicates compliance with r4, note: there is no value called 1
            entries.put(BUNDLE_MANIFESTVERSION, "2");
        if (entries.get(BUNDLE_NAME) == null) {
            // Bundle-Name is a human readable localizable name that can contain spaces
            entries.put(BUNDLE_NAME, pom.getName());
        if (entries.get(BUNDLE_SYMBOLICNAME) == null) {
            // OSGi convention is to use reverse domain name for SymbolicName, hence use .
            entries.put(BUNDLE_SYMBOLICNAME, pom.getGroupId()+'.'+pom.getArtifactId());
        if (entries.get(BUNDLE_VERSION) == null) {
            entries.put(BUNDLE_VERSION, VersionTranslator.MavenToOSGi(pom.getVersion()));
        if (entries.get(BUNDLE_DESCRIPTION) == null) {
            if (pom.getDescription()!=null)
                entries.put(BUNDLE_DESCRIPTION, pom.getDescription());
        if (entries.get(BUNDLE_VENDOR) == null) {
            if (pom.getOrganization()!=null && pom.getOrganization().getName() != null)
                entries.put(BUNDLE_VENDOR, pom.getOrganization().getName());
        // Handle Require-Bundle.
        if (entries.get(REQUIRE_BUNDLE) == null) {
            String requiredBundles = generateRequireBundleHeader(discoverRequiredBundles(pom));
            if (requiredBundles.length()>0) {
                entries.put(REQUIRE_BUNDLE, requiredBundles);
        // Handle Export-Package
        if (entries.get(EXPORT_PACKAGE) == null) {
            List<ExportedPackagepackages = discoverPackages(classesDirectory);
            // don't use version until we resolve split package issues in GF
            String exportPackages = generateExportPackageHeader(packagesnull);
            if (exportPackages.length()> 0) {
                entries.put(EXPORT_PACKAGE, exportPackages);
        return entries;
    static class BundleDependency {
        String bundleSymbolicName;
        String versionRange// version = 1.0.0.SNAPSHOT or "[1.0.0.SNAPSHOT, 1.0.0.SNAPSHOT]"
        String resolution// optional or mandatory
        String visibility// private or reexport
            throws IOException {
        List<BundleDependencydependencies = new ArrayList<BundleDependency>();
        for (Artifact a : (Set<Artifact>)pom.getDependencyArtifacts()) {
            if("test".equals(a.getScope()) || "provided".equals(a.getScope()))
            // indicates
            // that some artifacts are not resolved at this point. Not sure when that could happen
            // so aborting with diagnostics if we find it. We need to better understand what this
            // means and work accordingly. - KK
            if(a.getFile()==null) {
                throw new AssertionError(a.getId()+" is not resolved. a="+a);
            Attributes attributes = null;
            String name = null;
            Manifest manifest = Jar.create(a.getFile()).getManifest();
            if (manifest!=null) {
                attributes = manifest.getMainAttributes();
                name = attributes.getValue(BUNDLE_SYMBOLICNAME);
            if (name != null && attributes.getValue(FRAGMENT_HOST)==null) {
                // this is a OSGi host module 
                BundleDependency bd = new BundleDependency();
                bd.bundleSymbolicName = name;
                final String version = attributes.getValue(BUNDLE_VERSION);
                // no need to translate, for it's already an OSGi version
                bd.versionRange = version// maps to [version, infinity)
                // resolution=optional or mandatory
                bd.resolution = .getProperty("resolution", RESOLUTION_MANDATORY);
                bd.visibility = .getProperty("visibility", VISIBILITY_PRIVATE);
        return dependencies;
            List<BundleDependencydependencies) {
        // Require-Bundle:
        // a.b.c;version=1.0.0.b58g;resolution:=mandatory;visibility:=reexport,
        // p.q.r;version=1.0.0.SNAPSHOT;resolution:=optional;visibility:=private
        StringBuilder requiredBundles = new StringBuilder();
        for (BundleDependency bd : dependencies) {
            if(requiredBundles.length()!=0) {
            if(bd.versionRange!= null) {
        return requiredBundles.toString();
    static class ExportedPackage implements Comparable<ExportedPackage>{
        String packageName;
        Collection<StringpackagesUsed// uses directive
        public ExportedPackage(
                String packageName,
                Collection<StringpackagesUsed) {
            this. = packageName;
            this. = packagesUsed;
        public ExportedPackage(String packageName) {
        @Override public int hashCode() {
            return .hashCode();
        @Override public boolean equals(Object obj) {
            if (obj instanceof ExportedPackage) {
                return .equals(ExportedPackage.class.cast(obj).);
            return false;
        public int compareTo(ExportedPackage exportedPackage) {
            return this..compareTo(exportedPackage.packageName);
    public static List<ExportedPackagediscoverPackages(final File classesDirectory) {
        final List<ExportedPackagepackages = new ArrayList<ExportedPackage>();
                new FilenameFilter() {
                    public boolean accept(File dirString name) {
                        final File file = new File(dirname);
                        if (file.isDirectory()) {
                        final String CLASS_EXT = ".class";
                        if (!name.endsWith(CLASS_EXT)) {
                            return false;
                        final String packagePath = dir.getPath().substring(classesDirectory.getPath().length()+1);
                        String packageName = packagePath.replace(.'.');
                        .fine("packageName = " + packageName);
                        final ExportedPackage ep = new ExportedPackage(packageName);
                        if (!packages.contains(ep)) {
                        return true;
        return packages;
    public static String generateExportPackageHeader(
            Collection<ExportedPackagepackagesString version) {
        // Export-Packages=a.b.c;version=1.0.0.SNAPSHOT,p.q.r;x.y.z;version=2.0
        if (packages.isEmpty()) {
            return "";
        StringBuilder sb = new StringBuilder();
        for(ExportedPackage p : packages) {
            if(sb.length()>0) {
                sb.append(","); // exclude the first one
            // TODO: Make use of uses directive
            if (version!=null) {
        return sb.toString();
New to GrepCode? Check out our FAQ X