diff options
4 files changed, 222 insertions, 38 deletions
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/ClasspathEntry.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/ClasspathEntry.java index d6ddef5c6..168b49154 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/ClasspathEntry.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/ClasspathEntry.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2015 IBM Corporation and others. + * Copyright (c) 2005, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -13,6 +13,9 @@ package org.eclipse.osgi.internal.loader.classpath; import java.io.*; import java.security.ProtectionDomain; +import java.util.*; +import java.util.Map.Entry; +import java.util.jar.Attributes; import java.util.jar.Manifest; import org.eclipse.osgi.framework.util.KeyedElement; import org.eclipse.osgi.framework.util.KeyedHashSet; @@ -41,7 +44,8 @@ public class ClasspathEntry { private final BundleFile bundlefile; private final ProtectionDomain domain; - private final Manifest manifest; + private final ManifestPackageAttributes mainManifestPackageAttributes; + private final Map<String, ManifestPackageAttributes> perPackageManifestAttributes; private KeyedHashSet userObjects = null; // TODO Note that PDE has internal dependency on this field type/name (bug 267238) @@ -57,7 +61,40 @@ public class ClasspathEntry { this.bundlefile = bundlefile; this.domain = domain; this.data = new PDEData(generation.getBundleFile().getBaseFile(), generation.getRevision().getSymbolicName()); - this.manifest = getManifest(bundlefile, generation); + final Manifest manifest = loadManifest(bundlefile, generation); + if (manifest != null && generation.getBundleInfo().getStorage().getConfiguration().DEFINE_PACKAGE_ATTRIBUTES) { + mainManifestPackageAttributes = manifestPackageAttributesFor(manifest.getMainAttributes(), null); + perPackageManifestAttributes = manifestPackageAttributesMapFor(manifest.getEntries().entrySet(), mainManifestPackageAttributes); + } else { + mainManifestPackageAttributes = ManifestPackageAttributes.NONE; + perPackageManifestAttributes = null; + } + } + + private static ManifestPackageAttributes manifestPackageAttributesFor(Attributes attributes, ManifestPackageAttributes defaultAttributes) { + return ManifestPackageAttributes.of(attributes.getValue(Attributes.Name.SPECIFICATION_TITLE), // + attributes.getValue(Attributes.Name.SPECIFICATION_VERSION), // + attributes.getValue(Attributes.Name.SPECIFICATION_VENDOR), // + attributes.getValue(Attributes.Name.IMPLEMENTATION_TITLE), // + attributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION), // + attributes.getValue(Attributes.Name.IMPLEMENTATION_VENDOR), // + defaultAttributes); + } + + private static Map<String, ManifestPackageAttributes> manifestPackageAttributesMapFor(Set<Entry<String, Attributes>> entries, ManifestPackageAttributes defaultAttributes) { + Map<String, ManifestPackageAttributes> result = null; + for (Entry<String, Attributes> entry : entries) { + String name = entry.getKey(); + Attributes attributes = entry.getValue(); + if (name != null && name.endsWith("/")) { //$NON-NLS-1$ + String packageName = name.substring(0, name.length() - 1).replace('/', '.'); + if (result == null) { + result = new HashMap<String, ManifestPackageAttributes>(4); + } + result.put(packageName, manifestPackageAttributesFor(attributes, defaultAttributes)); + } + } + return result; } /** @@ -98,7 +135,7 @@ public class ClasspathEntry { userObjects.add(userObject); } - private static Manifest getManifest(BundleFile cpBundleFile, Generation generation) { + private static Manifest loadManifest(BundleFile cpBundleFile, Generation generation) { if (!generation.hasPackageInfo() && generation.getBundleFile() == cpBundleFile) { return null; } @@ -120,8 +157,12 @@ public class ClasspathEntry { return null; } - public Manifest getManifest() { - return this.manifest; + ManifestPackageAttributes manifestPackageAttributesFor(String packageName) { + ManifestPackageAttributes perPackage = perPackageManifestAttributes == null ? null : perPackageManifestAttributes.get(packageName); + if (perPackage != null) { + return perPackage; + } + return mainManifestPackageAttributes; } } diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/ClasspathManager.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/ClasspathManager.java index 3d475e214..0d3896607 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/ClasspathManager.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/ClasspathManager.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2015 IBM Corporation and others. + * Copyright (c) 2005, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -14,8 +14,6 @@ package org.eclipse.osgi.internal.loader.classpath; import java.io.*; import java.net.URL; import java.util.*; -import java.util.jar.Attributes; -import java.util.jar.Manifest; import org.eclipse.osgi.container.*; import org.eclipse.osgi.container.ModuleContainerAdaptor.ContainerEvent; import org.eclipse.osgi.container.namespaces.EquinoxModuleDataNamespace; @@ -657,35 +655,15 @@ public class ClasspathManager { String specTitle = null, specVersion = null, specVendor = null, implTitle = null, implVersion = null, implVendor = null; if (generation.getBundleInfo().getStorage().getConfiguration().DEFINE_PACKAGE_ATTRIBUTES) { - Manifest mf = classpathEntry.getManifest(); - if (mf != null) { - Attributes mainAttributes = mf.getMainAttributes(); - String dirName = packageName.replace('.', '/') + '/'; - Attributes packageAttributes = mf.getAttributes(dirName); - boolean noEntry = false; - if (packageAttributes == null) { - noEntry = true; - packageAttributes = mainAttributes; - } - specTitle = packageAttributes.getValue(Attributes.Name.SPECIFICATION_TITLE); - if (specTitle == null && !noEntry) - specTitle = mainAttributes.getValue(Attributes.Name.SPECIFICATION_TITLE); - specVersion = packageAttributes.getValue(Attributes.Name.SPECIFICATION_VERSION); - if (specVersion == null && !noEntry) - specVersion = mainAttributes.getValue(Attributes.Name.SPECIFICATION_VERSION); - specVendor = packageAttributes.getValue(Attributes.Name.SPECIFICATION_VENDOR); - if (specVendor == null && !noEntry) - specVendor = mainAttributes.getValue(Attributes.Name.SPECIFICATION_VENDOR); - implTitle = packageAttributes.getValue(Attributes.Name.IMPLEMENTATION_TITLE); - if (implTitle == null && !noEntry) - implTitle = mainAttributes.getValue(Attributes.Name.IMPLEMENTATION_TITLE); - implVersion = packageAttributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION); - if (implVersion == null && !noEntry) - implVersion = mainAttributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION); - implVendor = packageAttributes.getValue(Attributes.Name.IMPLEMENTATION_VENDOR); - if (implVendor == null && !noEntry) - implVendor = mainAttributes.getValue(Attributes.Name.IMPLEMENTATION_VENDOR); - } + ManifestPackageAttributes manifestPackageAttributes = classpathEntry.manifestPackageAttributesFor(packageName); + TitleVersionVendor specification = manifestPackageAttributes.getSpecification(); + TitleVersionVendor implementation = manifestPackageAttributes.getImplementation(); + specTitle = specification.getTitle(); + specVersion = specification.getVersion(); + specVendor = specification.getVendor(); + implTitle = implementation.getTitle(); + implVersion = implementation.getVersion(); + implVendor = implementation.getVendor(); } // The package is not defined yet define it before we define the class. diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/ManifestPackageAttributes.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/ManifestPackageAttributes.java new file mode 100644 index 000000000..1143a1207 --- /dev/null +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/ManifestPackageAttributes.java @@ -0,0 +1,95 @@ +/****************************************************************************** + * Copyright (c) 2016 Alex Blewitt and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Blewitt - initial API and implementation + ******************************************************************************/ +package org.eclipse.osgi.internal.loader.classpath; + +/** + * Stores a pair of {@link TitleVersionVendor} package attributes for the Implementation- and Specification- entries. + */ +class ManifestPackageAttributes { + /** + * Constant used when no titles, versions or vendors are specified for the package. + */ + static final ManifestPackageAttributes NONE = new ManifestPackageAttributes(TitleVersionVendor.NONE, TitleVersionVendor.NONE); + private final TitleVersionVendor implementation; + private final TitleVersionVendor specification; + + /** + * Utility method to return the first version, or the second if it is null + * @param first the string to return if not null + * @param second the fallback value if the first is null + * @return the first value, or the second value if the first is null + */ + private static String or(String first, String second) { + return first == null ? second : first; + } + + /** + * Factory method for creating ManifestPackageAttributes. If any of the given title, + * version, or vendor values are <code>null</code> then the defaultAttributes will be + * used. If the defaultAttributes is null or returns all <code>null</code> values then + * <code>null</code> values will be used. If <code>null</code> values are used for all of the + * versions, titles, and vendors then {@link #NONE} is returned. + * @param specificationTitle the package specification title + * @param specificationVersion the package specification version + * @param specificationVendor the package specification vendor + * @param implementationTitle the package implementation title + * @param implementationVersion the package implementation version + * @param implementationVendor the package implementation vendor + * @param defaultAttributes the default attributes to use when the specified title, version or vendor is <code>null</code>. + * @return + */ + static ManifestPackageAttributes of(String specificationTitle, String specificationVersion, String specificationVendor, String implementationTitle, String implementationVersion, String implementationVendor, ManifestPackageAttributes defaultAttributes) { + if (defaultAttributes == null) { + defaultAttributes = NONE; + } + return of(// + or(specificationTitle, defaultAttributes.getSpecification().getTitle()), // + or(specificationVersion, defaultAttributes.getSpecification().getVersion()), // + or(specificationVendor, defaultAttributes.getSpecification().getVendor()), // + or(implementationTitle, defaultAttributes.getImplementation().getTitle()), // + or(implementationVersion, defaultAttributes.getImplementation().getVersion()), // + or(implementationVendor, defaultAttributes.getImplementation().getVendor())// + ); + } + + private static ManifestPackageAttributes of(String specificationTitle, String specificationVersion, String specificationVendor, String implementationTitle, String implementationVersion, String implementationVendor) { + TitleVersionVendor specification = TitleVersionVendor.of(specificationTitle, specificationVersion, specificationVendor); + TitleVersionVendor implementation = TitleVersionVendor.of(implementationTitle, implementationVersion, implementationVendor); + if (specification == TitleVersionVendor.NONE && implementation == TitleVersionVendor.NONE) { + return NONE; + } + return new ManifestPackageAttributes(implementation, specification); + } + + private ManifestPackageAttributes(TitleVersionVendor implementation, TitleVersionVendor specification) { + if (implementation == null || specification == null) { + throw new IllegalArgumentException(); + } + this.implementation = implementation; + this.specification = specification; + } + + /** + * Returns the title, version and vendor for the package implementation. + * @return the title, version and vendor for the package implemetnation. + */ + TitleVersionVendor getImplementation() { + return implementation; + } + + /** + * Returns the title, version and vendor for the package specification. + * @return the title, version and vendor for the package specification. + */ + TitleVersionVendor getSpecification() { + return specification; + } +} diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/TitleVersionVendor.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/TitleVersionVendor.java new file mode 100644 index 000000000..b87d9264d --- /dev/null +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/TitleVersionVendor.java @@ -0,0 +1,70 @@ +/****************************************************************************** + * Copyright (c) 2016 Alex Blewitt and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Blewitt - initial API and implementation + ******************************************************************************/ + +package org.eclipse.osgi.internal.loader.classpath; + +/** + * Stores a (title,version,vendor) triple for Specification-* or Implementation-* + */ +class TitleVersionVendor { + /** + * Constant value when no title, version or vendor are specified for the package. + */ + static final TitleVersionVendor NONE = new TitleVersionVendor(null, null, null); + private final String title; + private final String version; + private final String vendor; + + /** + * Factory for creating TitleVersionVendor objects. If the given title, version and + * vendor are <code>null</code> then {@link #NONE} is returned. + * @param title + * @param version + * @param vendor + * @return + */ + static TitleVersionVendor of(String title, String version, String vendor) { + if (title == null && version == null && vendor == null) { + return NONE; + } + return new TitleVersionVendor(title, version, vendor); + } + + private TitleVersionVendor(String title, String version, String vendor) { + this.title = title; + this.version = version; + this.vendor = vendor; + } + + /** + * Returns the title + * @return the title + */ + String getTitle() { + return title; + } + + /** + * returns the version + * @return the version + */ + String getVersion() { + return version; + } + + /** + * returns the vendor + * @return the vendor + */ + String getVendor() { + return vendor; + } +} |