diff options
author | Thomas Watson | 2011-06-10 14:13:26 +0000 |
---|---|---|
committer | Thomas Watson | 2011-06-10 14:13:26 +0000 |
commit | e2171752cd585cf13e7539c1df2d998e1893251b (patch) | |
tree | d0e9592ed59bc34cffd217d91274c1fefe928077 | |
parent | 90b71dd24391575ef3a3ee2de91732cc6ef92869 (diff) | |
download | rt.equinox.framework-e2171752cd585cf13e7539c1df2d998e1893251b.tar.gz rt.equinox.framework-e2171752cd585cf13e7539c1df2d998e1893251b.tar.xz rt.equinox.framework-e2171752cd585cf13e7539c1df2d998e1893251b.zip |
Bug 346982 - BundleRequirement/BundleCapability getAttributes/getDirectives must return all specified values
15 files changed, 445 insertions, 29 deletions
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/services/resolver/StateResolverTest.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/services/resolver/StateResolverTest.java index 61b922132..0b6923323 100644 --- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/services/resolver/StateResolverTest.java +++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/services/resolver/StateResolverTest.java @@ -22,6 +22,7 @@ import org.eclipse.osgi.internal.resolver.StateObjectFactoryImpl; import org.eclipse.osgi.service.resolver.*; import org.eclipse.osgi.tests.OSGiTestsActivator; import org.osgi.framework.*; +import org.osgi.framework.wiring.*; public class StateResolverTest extends AbstractStateTest { public static Test suite() { @@ -3924,6 +3925,198 @@ public class StateResolverTest extends AbstractStateTest { ExportPackageDescription xExtra = state.linkDynamicImport(c1, "x.extra"); assertNotNull("x.extra dynamic import is null", xExtra); } + + public void testRequirements() throws BundleException, InvalidSyntaxException, IOException { + State state = buildEmptyState(); + long bundleID = 0; + Dictionary manifest; + + manifest = loadManifest("r1.MF"); + BundleDescription hostDescription = state.getFactory().createBundleDescription(state, manifest, (String) manifest.get(Constants.BUNDLE_SYMBOLICNAME), bundleID++); + state.addBundle(hostDescription); + manifest = loadManifest("r2.MF"); + BundleDescription fragDescription = state.getFactory().createBundleDescription(state, manifest, (String) manifest.get(Constants.BUNDLE_SYMBOLICNAME), bundleID++); + state.addBundle(fragDescription); + + doTestRequirements(hostDescription, fragDescription); + + File stateCache = OSGiTestsActivator.getContext().getDataFile("statecache"); //$NON-NLS-1$ + stateCache.mkdirs(); + StateObjectFactory.defaultFactory.writeState(state, stateCache); + state = StateObjectFactory.defaultFactory.readState(stateCache); + + hostDescription = state.getBundle(0); + fragDescription = state.getBundle(1); + + doTestRequirements(hostDescription, fragDescription); + } + + private void doTestRequirements(BundleRevision hostRevision, BundleRevision fragRevision) throws InvalidSyntaxException { + List pReqs = hostRevision.getDeclaredRequirements(BundleRevision.PACKAGE_NAMESPACE); + assertEquals("Wrong number of reqs: " + BundleRevision.PACKAGE_NAMESPACE, 8, pReqs.size()); + + Map matchingAttrs = new HashMap(); + matchingAttrs.put(BundleRevision.PACKAGE_NAMESPACE, "importer.pkg1"); + matchingAttrs.put(Constants.VERSION_ATTRIBUTE, new Version("1.1")); + + checkRequirement((BundleRequirement) pReqs.get(0), matchingAttrs, null, null, true); + + matchingAttrs.put(BundleRevision.PACKAGE_NAMESPACE, "importer.pkg2"); + checkRequirement((BundleRequirement) pReqs.get(1), matchingAttrs, null, "(resolution=optional)", true); + + matchingAttrs.put(BundleRevision.PACKAGE_NAMESPACE, "importer.pkg3"); + checkRequirement((BundleRequirement) pReqs.get(2), matchingAttrs, null, "(resolution=mandatory)", true); + + matchingAttrs.put(BundleRevision.PACKAGE_NAMESPACE, "importer.pkg4"); + checkRequirement((BundleRequirement) pReqs.get(3), matchingAttrs, null, null, true); + + matchingAttrs.put(BundleRevision.PACKAGE_NAMESPACE, "importer.pkg5"); + checkRequirement((BundleRequirement) pReqs.get(4), matchingAttrs, null, null, true); + + matchingAttrs.put(BundleRevision.PACKAGE_NAMESPACE, "importer.pkg6"); + checkRequirement((BundleRequirement) pReqs.get(5), matchingAttrs, null, null, true); + + matchingAttrs.put(BundleRevision.PACKAGE_NAMESPACE, "importer.pkg7"); + checkRequirement((BundleRequirement) pReqs.get(6), matchingAttrs, null, null, true); + + matchingAttrs.put(BundleRevision.PACKAGE_NAMESPACE, "importer.pkg8"); + matchingAttrs.put("a1", "v1"); + matchingAttrs.put("a2", "v2"); + checkRequirement((BundleRequirement) pReqs.get(7), matchingAttrs, null, "(&(resolution=optional)(d1=v1)(d2=v2))", true); + + matchingAttrs.clear(); + List bReqs = hostRevision.getDeclaredRequirements(BundleRevision.BUNDLE_NAMESPACE); + assertEquals("Wrong number of reqs: " + BundleRevision.BUNDLE_NAMESPACE, 8, bReqs.size()); + + matchingAttrs.put(BundleRevision.BUNDLE_NAMESPACE, "requirer.b1"); + matchingAttrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, new Version("1.1")); + checkRequirement((BundleRequirement) bReqs.get(0), matchingAttrs, null, "(&(visibility=reexport)(resolution=optional))", true); + + matchingAttrs.put(BundleRevision.BUNDLE_NAMESPACE, "requirer.b2"); + checkRequirement((BundleRequirement) bReqs.get(1), matchingAttrs, null, "(&(|(visibility=private)(!(visibility=*)))(|(resolution=mandatory)(!(resolution=*))))", true); + + matchingAttrs.put(BundleRevision.BUNDLE_NAMESPACE, "requirer.b3"); + checkRequirement((BundleRequirement) bReqs.get(2), matchingAttrs, null, null, true); + + matchingAttrs.put(BundleRevision.BUNDLE_NAMESPACE, "requirer.b4"); + checkRequirement((BundleRequirement) bReqs.get(3), matchingAttrs, null, null, true); + + matchingAttrs.put(BundleRevision.BUNDLE_NAMESPACE, "requirer.b5"); + checkRequirement((BundleRequirement) bReqs.get(4), matchingAttrs, null, null, true); + + matchingAttrs.put(BundleRevision.BUNDLE_NAMESPACE, "requirer.b6"); + checkRequirement((BundleRequirement) bReqs.get(5), matchingAttrs, null, null, true); + + matchingAttrs.put(BundleRevision.BUNDLE_NAMESPACE, "requirer.b7"); + checkRequirement((BundleRequirement) bReqs.get(6), matchingAttrs, null, null, true); + + matchingAttrs.put(BundleRevision.BUNDLE_NAMESPACE, "requirer.b8"); + matchingAttrs.put("a1", "v1"); + matchingAttrs.put("a2", "v2"); + checkRequirement((BundleRequirement) bReqs.get(7), matchingAttrs, null, "(&(resolution=optional)(d1=v1)(d2=v2))", true); + + matchingAttrs.clear(); + List cReqs = hostRevision.getDeclaredRequirements("require.c1"); + assertEquals("Wrong number of reqs: require.c1", 1, cReqs.size()); + + matchingAttrs.put("a1", "v1"); + checkRequirement((BundleRequirement) cReqs.get(0), matchingAttrs, null, "(&(|(effective=resolve)(!(effective=*)))(resolution=optional)(filter=\\(a1=v1\\)))", true); + + cReqs = hostRevision.getDeclaredRequirements("require.c2"); + assertEquals("Wrong number of reqs: require.c2", 1, cReqs.size()); + matchingAttrs.clear(); + checkRequirement((BundleRequirement) cReqs.get(0), matchingAttrs, null, "(&(|(effective=resolve)(!(effective=*)))(|(resolution=mandatory)(!(resolution=*))))", false); + + cReqs = hostRevision.getDeclaredRequirements("require.c3"); + assertEquals("Wrong number of reqs: require.c3", 1, cReqs.size()); + matchingAttrs.clear(); + checkRequirement((BundleRequirement) cReqs.get(0), matchingAttrs, "(&(a1=v1)(a2=v2))", "(&(resolution=optional)(d1=v1)(d2=v2))", false); + + List fReqs = fragRevision.getDeclaredRequirements(BundleRevision.HOST_NAMESPACE); + assertEquals("Wrong number of host reqs: " + BundleRevision.HOST_NAMESPACE, 1, fReqs.size()); + matchingAttrs.clear(); + matchingAttrs.put(BundleRevision.HOST_NAMESPACE, "r1"); + matchingAttrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, new Version(1, 1, 1)); + matchingAttrs.put("a1", "v1"); + matchingAttrs.put("a2", "v2"); + checkRequirement((BundleRequirement) fReqs.get(0), matchingAttrs, null, "(&(d1=v1)(d2=v2))", true); + } + + private void checkRequirement(BundleRequirement req, Map matchingAttrs, String attributesFilterSpec, String directivesFilterSpec, boolean reqFilter) throws InvalidSyntaxException { + if (attributesFilterSpec == null) { + assertTrue("Requirement attrs is not empty: " + req, req.getAttributes().isEmpty()); + } else { + Filter filter = FrameworkUtil.createFilter(attributesFilterSpec); + assertTrue("Cannot match attribute filter: " + filter, filter.matches(req.getAttributes())); + } + Map directives = req.getDirectives(); + String reqFilterSpec = (String) directives.get(Constants.FILTER_DIRECTIVE); + if (reqFilterSpec != null) { + Filter filter = FrameworkUtil.createFilter(reqFilterSpec); + assertTrue("Cannot match requirement filter: " + filter, filter.matches(matchingAttrs)); + } else { + if (reqFilter) + fail("Requirement must have filter directive: " + req); + } + if (directivesFilterSpec != null) { + Filter directivesFilter = FrameworkUtil.createFilter(directivesFilterSpec); + assertTrue("Cannot match directive filter: " + directivesFilterSpec, directivesFilter.matches(req.getDirectives())); + } + } + + public void testCapabilities() throws InvalidSyntaxException, BundleException, IOException { + State state = buildEmptyState(); + long bundleID = 0; + Dictionary manifest; + + manifest = loadManifest("r1.MF"); + BundleDescription hostDescription = state.getFactory().createBundleDescription(state, manifest, (String) manifest.get(Constants.BUNDLE_SYMBOLICNAME), bundleID++); + state.addBundle(hostDescription); + + doTestCapabilities(hostDescription); + + File stateCache = OSGiTestsActivator.getContext().getDataFile("statecache"); //$NON-NLS-1$ + stateCache.mkdirs(); + StateObjectFactory.defaultFactory.writeState(state, stateCache); + state = StateObjectFactory.defaultFactory.readState(stateCache); + + hostDescription = state.getBundle(0); + } + + private void doTestCapabilities(BundleRevision hostRevision) throws InvalidSyntaxException { + List bundleCaps = hostRevision.getDeclaredCapabilities(BundleRevision.BUNDLE_NAMESPACE); + assertEquals("Wrong number of: " + BundleRevision.BUNDLE_NAMESPACE, 1, bundleCaps.size()); + checkCapability((BundleCapability) bundleCaps.get(0), "(&(osgi.wiring.bundle=r1)(a1=v1)(a2=v2))", "(&(d1=v1)(d2=v2)(singleton=true)(fragment-attachment=resolve-time))"); + + List hostCaps = hostRevision.getDeclaredCapabilities(BundleRevision.HOST_NAMESPACE); + assertEquals("Wrong number of: " + BundleRevision.HOST_NAMESPACE, 1, hostCaps.size()); + checkCapability((BundleCapability) hostCaps.get(0), "(&(osgi.wiring.host=r1)(a1=v1)(a2=v2))", "(&(d1=v1)(d2=v2)(singleton=true)(fragment-attachment=resolve-time))"); + + List pkgCaps = hostRevision.getDeclaredCapabilities(BundleRevision.PACKAGE_NAMESPACE); + assertEquals("Wrong number of: " + BundleRevision.PACKAGE_NAMESPACE, 3, pkgCaps.size()); + checkCapability((BundleCapability) pkgCaps.get(0), "(&(osgi.wiring.package=exporter.pkg1)(bundle-symbolic-name=r1)(bundle-version=1.0)(version=1.0))", null); + checkCapability((BundleCapability) pkgCaps.get(1), "(&(osgi.wiring.package=exporter.pkg2)(bundle-symbolic-name=r1)(bundle-version=1.0)(a1=v1)(a2=v2))", "(&(include=C1,C2)(exclude=C3,C4)(mandatory=a1,a2)(uses=importer.pkg1,importer.pkg2))"); + checkCapability((BundleCapability) pkgCaps.get(2), "(&(osgi.wiring.package=exporter.pkg3)(bundle-symbolic-name=r1)(bundle-version=1.0)(a1=v1)(a2=v2))", "(&(mandatory=a1,a2)(d1=v1)(d2=v2))"); + + List gCaps = hostRevision.getDeclaredCapabilities("provide.c1"); + assertEquals("Wrong number of: provide.c1", 1, gCaps.size()); + checkCapability((BundleCapability) gCaps.get(0), "(&(a1=v1)(a2=v2))", "(&(|(effective=resolve)(!(effective=*)))(uses=importer.pkg1,importer.pkg2))"); + + gCaps = hostRevision.getDeclaredCapabilities("provide.c2"); + assertEquals("Wrong number of: provide.c1", 1, gCaps.size()); + checkCapability((BundleCapability) gCaps.get(0), "(&(a1=v1)(a2=v2))", "(&(|(effective=resolve)(!(effective=*)))(uses=importer.pkg1,importer.pkg2)(d1=v1)(d2=v2))"); + + } + + private void checkCapability(BundleCapability cap, String attributeFilterSpec, String directiveFilterSpec) throws InvalidSyntaxException { + Filter attributesFilter = FrameworkUtil.createFilter(attributeFilterSpec); + assertTrue("Cannot match attribute filter: " + attributesFilter, attributesFilter.matches(cap.getAttributes())); + + if (directiveFilterSpec != null) { + Filter directivesFilter = FrameworkUtil.createFilter(directiveFilterSpec); + assertTrue("Cannot match directive filter: " + directivesFilter, directivesFilter.matches(cap.getDirectives())); + } + } } //testFragmentUpdateNoVersionChanged() //testFragmentUpdateVersionChanged() diff --git a/bundles/org.eclipse.osgi.tests/test_files/resolverTests/r1.MF b/bundles/org.eclipse.osgi.tests/test_files/resolverTests/r1.MF new file mode 100644 index 000000000..0a168db4d --- /dev/null +++ b/bundles/org.eclipse.osgi.tests/test_files/resolverTests/r1.MF @@ -0,0 +1,33 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-SymbolicName: r1; singleton:=true; fragment-attachment:="resolve-time"; d1:=v1; d2:=v2; a1=v1; a2=v2 +Bundle-Version: 1.0 +Import-Package: + importer.pkg1; version="1.0", + importer.pkg2; resolution:=optional, + importer.pkg3; resolution:=mandatory, + importer.pkg4; version="(1.0,2.0)", + importer.pkg5; version="[1.0,2.0)", + importer.pkg6; version="(1.0,2.0]", + importer.pkg7; version="[1.0,2.0]", + importer.pkg8; resolution:=optional; d1:=v1; d2:=v2; a1=v1; a2=v2 +Export-Package: + exporter.pkg1; version="1.0", + exporter.pkg2; include:="C1,C2"; exclude:="C3,C4"; mandatory:="a1,a2"; uses:="importer.pkg1,importer.pkg2"; a1=v1; a2=v2, + exporter.pkg3; mandatory:="a1,a2"; d1:=v1; d2:=v2; a1=v1; a2=v2 +Require-Bundle: + requirer.b1; visibility:=reexport; resolution:=optional, + requirer.b2; visibility:=private; resolution:=mandatory, + requirer.b3; bundle-version="1.0", + requirer.b4; bundle-version="(1.0,2.0)", + requirer.b5; bundle-version="[1.0,2.0)", + requirer.b6; bundle-version="(1.0,2.0]", + requirer.b7; bundle-version="[1.0,2.0]", + requirer.b8; resolution:=optional; d1:=v1; d2:=v2; a1=v1; a2=v2 +Require-Capability: + require.c1; effective:=resolve; resolution:=optional; filter:=(a1=v1), + require.c2; resolution:=mandatory, + require.c3; resolution:=optional; d1:=v1; d2:=v2; a1=v1; a2=v2 +Provide-Capability: + provide.c1; effective:=resolve; uses:="importer.pkg1,importer.pkg2"; a1=v1; a2=v2, + provide.c2; uses:="importer.pkg1,importer.pkg2"; d1:=v1; d2:=v2; a1=v1; a2=v2 diff --git a/bundles/org.eclipse.osgi.tests/test_files/resolverTests/r2.MF b/bundles/org.eclipse.osgi.tests/test_files/resolverTests/r2.MF new file mode 100644 index 000000000..de2c03214 --- /dev/null +++ b/bundles/org.eclipse.osgi.tests/test_files/resolverTests/r2.MF @@ -0,0 +1,5 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-SymbolicName: r2; singleton:=true +Bundle-Version: 1.0 +Fragment-Host: r1; bundle-version="[1.0, 2.0)"; d1:=v1; d2:=v2; a1=v1; a2=v2 diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BaseDescriptionImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BaseDescriptionImpl.java index c158d325f..fa47b2c99 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BaseDescriptionImpl.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BaseDescriptionImpl.java @@ -12,6 +12,7 @@ package org.eclipse.osgi.internal.resolver; import java.util.*; +import java.util.Map.Entry; import org.eclipse.osgi.service.resolver.BaseDescription; import org.osgi.framework.Version; import org.osgi.framework.wiring.BundleCapability; @@ -45,13 +46,13 @@ public abstract class BaseDescriptionImpl implements BaseDescription { this.version = version; } - static String toString(Map<String, Object> map, boolean directives) { + static <V> String toString(Map<String, V> map, boolean directives) { if (map.size() == 0) return ""; //$NON-NLS-1$ String assignment = directives ? ":=" : "="; //$NON-NLS-1$//$NON-NLS-2$ - Set<Map.Entry<String, Object>> set = map.entrySet(); + Set<Entry<String, V>> set = map.entrySet(); StringBuffer sb = new StringBuffer(); - for (Map.Entry<String, Object> entry : set) { + for (Entry<String, V> entry : set) { sb.append("; "); //$NON-NLS-1$ String key = entry.getKey(); Object value = entry.getValue(); @@ -153,7 +154,7 @@ public abstract class BaseDescriptionImpl implements BaseDescription { } public String toString() { - return getNamespace() + BaseDescriptionImpl.toString(getAttributes(), false); + return getNamespace() + BaseDescriptionImpl.toString(getAttributes(), false) + BaseDescriptionImpl.toString(getDirectives(), true); } } } diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BundleDescriptionImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BundleDescriptionImpl.java index 1f6cfdd52..f2e4205ae 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BundleDescriptionImpl.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BundleDescriptionImpl.java @@ -58,6 +58,7 @@ public final class BundleDescriptionImpl extends BaseDescriptionImpl implements private List<BundleDescription> dependents; private String[] mandatory; private Map<String, Object> attributes; + private Map<String, String> arbitraryDirectives; private volatile LazyData lazyData; private volatile int equinox_ee = -1; @@ -857,8 +858,24 @@ public final class BundleDescriptionImpl extends BaseDescriptionImpl implements mandatory = (String[]) value; } + @SuppressWarnings("unchecked") + void setArbitraryDirectives(Map<String, ?> directives) { + synchronized (this.monitor) { + this.arbitraryDirectives = (Map<String, String>) directives; + } + } + + Map<String, String> getArbitraryDirectives() { + synchronized (this.monitor) { + return arbitraryDirectives; + } + } + public Map<String, String> getDeclaredDirectives() { Map<String, String> result = new HashMap<String, String>(2); + Map<String, String> arbitrary = getArbitraryDirectives(); + if (arbitrary != null) + result.putAll(arbitrary); if (!attachFragments()) { result.put(Constants.FRAGMENT_ATTACHMENT_DIRECTIVE, Constants.FRAGMENT_ATTACHMENT_NEVER); } else { diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BundleSpecificationImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BundleSpecificationImpl.java index 71bdc2fe8..0e1577645 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BundleSpecificationImpl.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BundleSpecificationImpl.java @@ -20,6 +20,7 @@ public class BundleSpecificationImpl extends VersionConstraintImpl implements Bu private boolean exported; private boolean optional; private Map<String, Object> attributes; + private Map<String, String> arbitraryDirectives; protected void setExported(boolean exported) { synchronized (this.monitor) { @@ -58,6 +59,19 @@ public class BundleSpecificationImpl extends VersionConstraintImpl implements Bu } } + Map<String, String> getArbitraryDirectives() { + synchronized (this.monitor) { + return arbitraryDirectives; + } + } + + @SuppressWarnings("unchecked") + void setArbitraryDirectives(Map<String, ?> directives) { + synchronized (this.monitor) { + this.arbitraryDirectives = (Map<String, String>) directives; + } + } + public boolean isSatisfiedBy(BaseDescription supplier) { if (!(supplier instanceof BundleDescriptionImpl)) return false; @@ -98,6 +112,8 @@ public class BundleSpecificationImpl extends VersionConstraintImpl implements Bu protected Map<String, String> getInternalDirectives() { Map<String, String> result = new HashMap<String, String>(2); synchronized (this.monitor) { + if (arbitraryDirectives != null) + result.putAll(arbitraryDirectives); if (exported) result.put(Constants.VISIBILITY_DIRECTIVE, Constants.VISIBILITY_REEXPORT); if (optional) diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ExportPackageDescriptionImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ExportPackageDescriptionImpl.java index a76444518..795f3a2b1 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ExportPackageDescriptionImpl.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ExportPackageDescriptionImpl.java @@ -23,6 +23,7 @@ public class ExportPackageDescriptionImpl extends BaseDescriptionImpl implements private static final Integer EQUINOX_EE_DEFAULT = new Integer(-1); private String[] uses; private Map<String, Object> attributes; + private Map<String, String> arbitraryDirectives; private volatile BundleDescription exporter; private String exclude; private String include; @@ -40,6 +41,7 @@ public class ExportPackageDescriptionImpl extends BaseDescriptionImpl implements setName(fragmentDeclaration.getName()); setVersion(fragmentDeclaration.getVersion()); setDirectives(fragmentDeclaration.getDirectives()); + setArbitraryDirectives(((ExportPackageDescriptionImpl) fragmentDeclaration).getArbitraryDirectives()); setAttributes(fragmentDeclaration.getAttributes()); setExporter(host); this.fragmentDeclaration = fragmentDeclaration; @@ -67,6 +69,9 @@ public class ExportPackageDescriptionImpl extends BaseDescriptionImpl implements public Map<String, String> getDeclaredDirectives() { Map<String, String> result = new HashMap<String, String>(6); synchronized (this.monitor) { + Map<String, String> arbitrary = getArbitraryDirectives(); + if (arbitrary != null) + result.putAll(arbitrary); if (uses != null) result.put(Constants.USES_DIRECTIVE, toString(uses)); if (exclude != null) @@ -165,6 +170,19 @@ public class ExportPackageDescriptionImpl extends BaseDescriptionImpl implements } } + @SuppressWarnings("unchecked") + void setArbitraryDirectives(Map<String, ?> directives) { + synchronized (this.monitor) { + this.arbitraryDirectives = (Map<String, String>) directives; + } + } + + Map<String, String> getArbitraryDirectives() { + synchronized (this.monitor) { + return arbitraryDirectives; + } + } + public Map<String, Object> getAttributes() { synchronized (this.monitor) { return attributes; diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/GenericSpecificationImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/GenericSpecificationImpl.java index 43aae96f1..296f70f79 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/GenericSpecificationImpl.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/GenericSpecificationImpl.java @@ -21,6 +21,8 @@ public class GenericSpecificationImpl extends VersionConstraintImpl implements G private String type = GenericDescription.DEFAULT_TYPE; private int resolution = 0; private GenericDescription[] suppliers; + private Map<String, Object> attributes; + private Map<String, String> arbitraryDirectives; public String getMatchingFilter() { synchronized (this.monitor) { @@ -129,10 +131,38 @@ public class GenericSpecificationImpl extends VersionConstraintImpl implements G } } + Map<String, Object> getAttributes() { + synchronized (this.monitor) { + return attributes; + } + } + + @SuppressWarnings("unchecked") + void setAttributes(Map<String, ?> attributes) { + synchronized (this.monitor) { + this.attributes = (Map<String, Object>) attributes; + } + } + + Map<String, String> getArbitraryDirectives() { + synchronized (this.monitor) { + return arbitraryDirectives; + } + } + + @SuppressWarnings("unchecked") + void setArbitraryDirectives(Map<String, ?> directives) { + synchronized (this.monitor) { + this.arbitraryDirectives = (Map<String, String>) directives; + } + } + @Override protected Map<String, String> getInternalDirectives() { Map<String, String> result = new HashMap<String, String>(2); synchronized (this.monitor) { + if (arbitraryDirectives != null) + result.putAll(arbitraryDirectives); if ((resolution & GenericSpecification.RESOLUTION_OPTIONAL) != 0) result.put(Constants.RESOLUTION_DIRECTIVE, Constants.RESOLUTION_OPTIONAL); if (matchingFilter != null) { @@ -145,8 +175,9 @@ public class GenericSpecificationImpl extends VersionConstraintImpl implements G @SuppressWarnings("unchecked") @Override protected Map<String, Object> getInteralAttributes() { - // TODO this needs to return all specified attributes from the Require-Capability header. - return Collections.EMPTY_MAP; + synchronized (this.monitor) { + return attributes == null ? Collections.EMPTY_MAP : new HashMap<String, Object>(attributes); + } } @Override diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/HostSpecificationImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/HostSpecificationImpl.java index 08a9d0ace..82b453716 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/HostSpecificationImpl.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/HostSpecificationImpl.java @@ -22,6 +22,7 @@ public class HostSpecificationImpl extends VersionConstraintImpl implements Host private BundleDescription[] hosts; private boolean multihost = false; private Map<String, Object> attributes; + private Map<String, String> arbitraryDirectives; Map<String, Object> getAttributes() { synchronized (this.monitor) { @@ -36,6 +37,19 @@ public class HostSpecificationImpl extends VersionConstraintImpl implements Host } } + Map<String, String> getArbitraryDirectives() { + synchronized (this.monitor) { + return arbitraryDirectives; + } + } + + @SuppressWarnings("unchecked") + void setArbitraryDirectives(Map<String, ?> directives) { + synchronized (this.monitor) { + this.arbitraryDirectives = (Map<String, String>) directives; + } + } + public boolean isSatisfiedBy(BaseDescription supplier) { if (!(supplier instanceof BundleDescriptionImpl)) return false; @@ -113,12 +127,12 @@ public class HostSpecificationImpl extends VersionConstraintImpl implements Host } } - @SuppressWarnings("unchecked") @Override protected Map<String, String> getInternalDirectives() { - // TODO this does not handle extension directive; but we do not support bootclasspath anyway Map<String, String> result = new HashMap<String, String>(2); synchronized (this.monitor) { + if (arbitraryDirectives != null) + result.putAll(arbitraryDirectives); result.put(Constants.FILTER_DIRECTIVE, createFilterDirective()); return result; } diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ImportPackageSpecificationImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ImportPackageSpecificationImpl.java index ac21cbe68..a1966c2a1 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ImportPackageSpecificationImpl.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ImportPackageSpecificationImpl.java @@ -22,6 +22,7 @@ public class ImportPackageSpecificationImpl extends VersionConstraintImpl implem private String symbolicName; private VersionRange bundleVersionRange; private Map<String, Object> attributes; + private Map<String, String> arbitraryDirectives; public Map<String, Object> getDirectives() { synchronized (this.monitor) { @@ -40,7 +41,7 @@ public class ImportPackageSpecificationImpl extends VersionConstraintImpl implem } } - public Object setDirective(String key, Object value) { + Object setDirective(String key, Object value) { synchronized (this.monitor) { if (key.equals(Constants.RESOLUTION_DIRECTIVE)) return resolution = (String) value; @@ -48,7 +49,7 @@ public class ImportPackageSpecificationImpl extends VersionConstraintImpl implem } } - public void setDirectives(Map<String, ?> directives) { + void setDirectives(Map<String, ?> directives) { synchronized (this.monitor) { if (directives == null) return; @@ -56,6 +57,19 @@ public class ImportPackageSpecificationImpl extends VersionConstraintImpl implem } } + @SuppressWarnings("unchecked") + void setArbitraryDirectives(Map<String, ?> directives) { + synchronized (this.monitor) { + this.arbitraryDirectives = (Map<String, String>) directives; + } + } + + Map<String, String> getArbitraryDirectives() { + synchronized (this.monitor) { + return arbitraryDirectives; + } + } + public String getBundleSymbolicName() { synchronized (this.monitor) { if (Constants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(symbolicName)) { @@ -184,12 +198,21 @@ public class ImportPackageSpecificationImpl extends VersionConstraintImpl implem return "Import-Package: " + getName() + "; version=\"" + getVersionRange() + "\""; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } - @SuppressWarnings({"unchecked", "rawtypes"}) @Override protected Map<String, String> getInternalDirectives() { - Map raw = getDirectives(); - raw.put(Constants.FILTER_DIRECTIVE, createFilterDirective()); - return raw; + synchronized (this.monitor) { + Map<String, String> result = new HashMap<String, String>(5); + if (arbitraryDirectives != null) + result.putAll(arbitraryDirectives); + if (resolution != null) { + if (ImportPackageSpecification.RESOLUTION_STATIC.equals(resolution)) + result.put(Constants.RESOLUTION_DIRECTIVE, Constants.RESOLUTION_MANDATORY); + else + result.put(Constants.RESOLUTION_DIRECTIVE, resolution); + } + result.put(Constants.FILTER_DIRECTIVE, createFilterDirective()); + return result; + } } private String createFilterDirective() { diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateBuilder.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateBuilder.java index 60720acab..db90b9dda 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateBuilder.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateBuilder.java @@ -24,9 +24,16 @@ import org.osgi.framework.*; * This class builds bundle description objects from manifests */ public class StateBuilder { - static final String[] DEFINED_PACKAGE_MATCHING_ATTRS = {Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE, Constants.BUNDLE_VERSION_ATTRIBUTE, Constants.PACKAGE_SPECIFICATION_VERSION, Constants.VERSION_ATTRIBUTE}; - static final String[] DEFINED_BSN_MATCHING_ATTRS = {Constants.BUNDLE_VERSION_ATTRIBUTE, Constants.OPTIONAL_ATTRIBUTE, Constants.REPROVIDE_ATTRIBUTE}; - static final String[] DEFINED_OSGI_VALIDATE_HEADERS = {Constants.IMPORT_PACKAGE, Constants.DYNAMICIMPORT_PACKAGE, Constants.EXPORT_PACKAGE, Constants.FRAGMENT_HOST, Constants.BUNDLE_SYMBOLICNAME, Constants.REQUIRE_BUNDLE}; + private static final String[] DEFINED_EXPORT_PACKAGE_DIRECTIVES = {Constants.USES_DIRECTIVE, Constants.INCLUDE_DIRECTIVE, Constants.EXCLUDE_DIRECTIVE, Constants.FRIENDS_DIRECTIVE, Constants.INTERNAL_DIRECTIVE, Constants.MANDATORY_DIRECTIVE}; + private static final String[] DEFINED_IMPORT_PACKAGE_DIRECTIVES = {Constants.RESOLUTION_DIRECTIVE}; + private static final String[] DEFINED_PACKAGE_MATCHING_ATTRS = {Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE, Constants.BUNDLE_VERSION_ATTRIBUTE, Constants.PACKAGE_SPECIFICATION_VERSION, Constants.VERSION_ATTRIBUTE}; + private static final String[] DEFINED_REQUIRE_BUNDLE_DIRECTIVES = {Constants.RESOLUTION_DIRECTIVE, Constants.VISIBILITY_DIRECTIVE}; + private static final String[] DEFINED_FRAGMENT_HOST_DIRECTIVES = {Constants.EXTENSION_DIRECTIVE}; + private static final String[] DEFINED_BSN_DIRECTIVES = {Constants.SINGLETON_DIRECTIVE, Constants.FRAGMENT_ATTACHMENT_DIRECTIVE, Constants.MANDATORY_DIRECTIVE}; + private static final String[] DEFINED_BSN_MATCHING_ATTRS = {Constants.BUNDLE_VERSION_ATTRIBUTE, Constants.OPTIONAL_ATTRIBUTE, Constants.REPROVIDE_ATTRIBUTE}; + private static final String[] DEFINED_REQUIRE_CAPABILITY_DIRECTIVES = {Constants.RESOLUTION_DIRECTIVE, Constants.FILTER_DIRECTIVE}; + private static final String[] DEFINED_REQUIRE_CAPABILITY_ATTRS = {}; + private static final String[] DEFINED_OSGI_VALIDATE_HEADERS = {Constants.IMPORT_PACKAGE, Constants.DYNAMICIMPORT_PACKAGE, Constants.EXPORT_PACKAGE, Constants.FRAGMENT_HOST, Constants.BUNDLE_SYMBOLICNAME, Constants.REQUIRE_BUNDLE}; static final String GENERIC_REQUIRE = "Eclipse-GenericRequire"; //$NON-NLS-1$ static final String GENERIC_CAPABILITY = "Eclipse-GenericCapability"; //$NON-NLS-1$ @@ -74,6 +81,7 @@ public class StateBuilder { } result.setDirective(Constants.MANDATORY_DIRECTIVE, ManifestElement.getArrayFromList(bsnElement.getDirective(Constants.MANDATORY_DIRECTIVE))); result.setAttributes(getAttributes(bsnElement, DEFINED_BSN_MATCHING_ATTRS)); + result.setArbitraryDirectives(getDirectives(bsnElement, DEFINED_BSN_DIRECTIVES)); } } // retrieve other headers @@ -225,6 +233,7 @@ public class StateBuilder { result.setExported(Constants.VISIBILITY_REEXPORT.equals(spec.getDirective(Constants.VISIBILITY_DIRECTIVE)) || "true".equals(spec.getAttribute(Constants.REPROVIDE_ATTRIBUTE))); //$NON-NLS-1$ result.setOptional(Constants.RESOLUTION_OPTIONAL.equals(spec.getDirective(Constants.RESOLUTION_DIRECTIVE)) || "true".equals(spec.getAttribute(Constants.OPTIONAL_ATTRIBUTE))); //$NON-NLS-1$ result.setAttributes(getAttributes(spec, DEFINED_BSN_MATCHING_ATTRS)); + result.setArbitraryDirectives(getDirectives(spec, DEFINED_REQUIRE_BUNDLE_DIRECTIVES)); return result; } @@ -287,6 +296,7 @@ public class StateBuilder { result.setDirective(Constants.RESOLUTION_DIRECTIVE, ImportPackageSpecification.RESOLUTION_DYNAMIC); else result.setDirective(Constants.RESOLUTION_DIRECTIVE, getResolution(importPackage.getDirective(Constants.RESOLUTION_DIRECTIVE))); + result.setArbitraryDirectives(getDirectives(importPackage, DEFINED_IMPORT_PACKAGE_DIRECTIVES)); allImports.add(result); } @@ -332,6 +342,7 @@ public class StateBuilder { result.setDirective(Constants.INTERNAL_DIRECTIVE, Boolean.valueOf(exportPackage.getDirective(Constants.INTERNAL_DIRECTIVE))); result.setDirective(Constants.MANDATORY_DIRECTIVE, ManifestElement.getArrayFromList(exportPackage.getDirective(Constants.MANDATORY_DIRECTIVE))); result.setAttributes(getAttributes(exportPackage, DEFINED_PACKAGE_MATCHING_ATTRS)); + result.setArbitraryDirectives(getDirectives(exportPackage, DEFINED_EXPORT_PACKAGE_DIRECTIVES)); allExports.add(result); } } @@ -354,6 +365,24 @@ public class StateBuilder { } } + private static Map<String, String> getDirectives(ManifestElement element, String[] definedDirectives) { + Enumeration<String> keys = element.getDirectiveKeys(); + if (keys == null) + return null; + Map<String, String> arbitraryDirectives = null; + keyloop: while (keys.hasMoreElements()) { + String key = keys.nextElement(); + for (String definedDirective : definedDirectives) { + if (definedDirective.equals(key)) + continue keyloop; + } + if (arbitraryDirectives == null) + arbitraryDirectives = new HashMap<String, String>(); + arbitraryDirectives.put(key, element.getDirective(key)); + } + return arbitraryDirectives; + } + private static Map<String, Object> getAttributes(ManifestElement element, String[] definedAttrs) { Enumeration<String> keys = element.getKeys(); Map<String, Object> arbitraryAttrs = null; @@ -443,6 +472,7 @@ public class StateBuilder { multiple = getPlatformProperty(state, "osgi.support.multipleHosts"); //$NON-NLS-1$ result.setIsMultiHost("true".equals(multiple)); //$NON-NLS-1$ result.setAttributes(getAttributes(spec, DEFINED_BSN_MATCHING_ATTRS)); + result.setArbitraryDirectives(getDirectives(spec, DEFINED_FRAGMENT_HOST_DIRECTIVES)); return result; } @@ -482,6 +512,8 @@ public class StateBuilder { String resolution = element.getDirective(Constants.RESOLUTION_DIRECTIVE); if (Constants.RESOLUTION_OPTIONAL.equals(resolution)) spec.setResolution(GenericSpecification.RESOLUTION_OPTIONAL); + spec.setAttributes(getAttributes(element, DEFINED_REQUIRE_CAPABILITY_ATTRS)); + spec.setArbitraryDirectives(getDirectives(element, DEFINED_REQUIRE_CAPABILITY_DIRECTIVES)); result.add(spec); } } diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateObjectFactoryImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateObjectFactoryImpl.java index 23426abda..df97bf13a 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateObjectFactoryImpl.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateObjectFactoryImpl.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003, 2010 IBM Corporation and others. + * Copyright (c) 2003, 2011 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 @@ -107,8 +107,10 @@ public class StateObjectFactoryImpl implements StateObjectFactory { bundle.setGenericRequires(createGenericRequires(original.getGenericRequires())); bundle.setNativeCodeSpecification(createNativeCodeSpecification(original.getNativeCodeSpecification())); bundle.setAttributes(original.getAttributes()); - if (original instanceof BundleDescriptionImpl) + if (original instanceof BundleDescriptionImpl) { bundle.setDirective(Constants.MANDATORY_DIRECTIVE, ((BundleDescriptionImpl) original).getDirective(Constants.MANDATORY_DIRECTIVE)); + bundle.setArbitraryDirectives(((BundleDescriptionImpl) original).getArbitraryDirectives()); + } return bundle; } @@ -162,10 +164,14 @@ public class StateObjectFactoryImpl implements StateObjectFactory { req.setType(genericRequires[i].getType()); req.setResolution(req.getResolution()); try { - req.setMatchingFilter(genericRequires[i].getMatchingFilter(), true); + req.setMatchingFilter(genericRequires[i].getMatchingFilter(), false); } catch (InvalidSyntaxException e) { // do nothing; this filter should already have been tested } + if (genericRequires[i] instanceof GenericSpecificationImpl) { + req.setAttributes(((GenericSpecificationImpl) genericRequires[i]).getAttributes()); + req.setArbitraryDirectives(((GenericSpecificationImpl) genericRequires[i]).getArbitraryDirectives()); + } result[i] = req; } return result; @@ -186,8 +192,10 @@ public class StateObjectFactoryImpl implements StateObjectFactory { bundleSpec.setVersionRange(original.getVersionRange()); bundleSpec.setExported(original.isExported()); bundleSpec.setOptional(original.isOptional()); - if (original instanceof BundleSpecificationImpl) + if (original instanceof BundleSpecificationImpl) { bundleSpec.setAttributes(((BundleSpecificationImpl) original).getAttributes()); + bundleSpec.setArbitraryDirectives(((BundleSpecificationImpl) original).getArbitraryDirectives()); + } return bundleSpec; } @@ -202,8 +210,10 @@ public class StateObjectFactoryImpl implements StateObjectFactory { HostSpecificationImpl hostSpec = new HostSpecificationImpl(); hostSpec.setName(original.getName()); hostSpec.setVersionRange(original.getVersionRange()); - if (original instanceof HostSpecificationImpl) + if (original instanceof HostSpecificationImpl) { hostSpec.setAttributes(((HostSpecificationImpl) original).getAttributes()); + hostSpec.setArbitraryDirectives(((HostSpecificationImpl) original).getArbitraryDirectives()); + } return hostSpec; } @@ -227,11 +237,20 @@ public class StateObjectFactoryImpl implements StateObjectFactory { packageSpec.setBundleVersionRange(original.getBundleVersionRange()); packageSpec.setDirectives(original.getDirectives()); packageSpec.setAttributes(original.getAttributes()); + if (original instanceof ImportPackageSpecificationImpl) { + packageSpec.setArbitraryDirectives(((ImportPackageSpecificationImpl) original).getArbitraryDirectives()); + } return packageSpec; } public ExportPackageDescription createExportPackageDescription(ExportPackageDescription original) { - return createExportPackageDescription(original.getName(), original.getVersion(), original.getDirectives(), original.getAttributes(), true, null); + ExportPackageDescriptionImpl exportPackage = new ExportPackageDescriptionImpl(); + exportPackage.setName(original.getName()); + exportPackage.setVersion(original.getVersion()); + exportPackage.setDirectives(original.getDirectives()); + exportPackage.setAttributes(original.getAttributes()); + exportPackage.setArbitraryDirectives(((ExportPackageDescriptionImpl) original).getArbitraryDirectives()); + return exportPackage; } public ExportPackageDescription createExportPackageDescription(String packageName, Version version, Map<String, ?> directives, Map<String, ?> attributes, boolean root, BundleDescription exporter) { diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateReader.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateReader.java index f26ce5f2d..bcf2baaf8 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateReader.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateReader.java @@ -46,7 +46,7 @@ final class StateReader { private volatile int numBundles; private volatile boolean accessedFlag = false; - public static final byte STATE_CACHE_VERSION = 36; + public static final byte STATE_CACHE_VERSION = 37; public static final byte NULL = 0; public static final byte OBJECT = 1; public static final byte INDEX = 2; @@ -226,6 +226,7 @@ final class StateReader { if (mandatory != null) result.setDirective(Constants.MANDATORY_DIRECTIVE, mandatory); result.setAttributes(readMap(in)); + result.setArbitraryDirectives(readMap(in)); result.setHost(readHostSpec(in)); // set the bundle dependencies from imports and requires and hosts. @@ -397,6 +398,7 @@ final class StateReader { result.setExported(in.readBoolean()); result.setOptional(in.readBoolean()); result.setAttributes(readMap(in)); + result.setArbitraryDirectives(readMap(in)); return result; } @@ -413,6 +415,7 @@ final class StateReader { exportPackageDesc.setExporter(readBundleDescription(in)); exportPackageDesc.setAttributes(readMap(in)); exportPackageDesc.setDirectives(readMap(in)); + exportPackageDesc.setArbitraryDirectives(readMap(in)); exportPackageDesc.setFragmentDeclaration(readExportPackageDesc(in)); return exportPackageDesc; } @@ -555,6 +558,7 @@ final class StateReader { result.setBundleVersionRange(readVersionRange(in)); result.setAttributes(readMap(in)); result.setDirectives(readMap(in)); + result.setArbitraryDirectives(readMap(in)); return result; } @@ -576,6 +580,7 @@ final class StateReader { result.setHosts(hosts); } result.setAttributes(readMap(in)); + result.setArbitraryDirectives(readMap(in)); return result; } @@ -629,6 +634,8 @@ final class StateReader { } catch (InvalidSyntaxException e) { // do nothing this filter was tested before } + result.setAttributes(readMap(in)); + result.setArbitraryDirectives(readMap(in)); return result; } diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateWriter.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateWriter.java index 6ecc5960d..e1ec84ff1 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateWriter.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateWriter.java @@ -217,6 +217,7 @@ class StateWriter { out.writeBoolean(bundle.dynamicFragments()); writeList(out, (String[]) ((BundleDescriptionImpl) bundle).getDirective(Constants.MANDATORY_DIRECTIVE)); writeMap(out, bundle.getAttributes()); + writeMap(out, ((BundleDescriptionImpl) bundle).getArbitraryDirectives()); writeHostSpec((HostSpecificationImpl) bundle.getHost(), out, force); List<BundleDescription> dependencies = ((BundleDescriptionImpl) bundle).getBundleDependencies(); @@ -243,7 +244,7 @@ class StateWriter { ImportPackageSpecification[] imports = bundle.getImportPackages(); out.writeInt(imports.length); for (int i = 0; i < imports.length; i++) - writeImportPackageSpec(imports[i], out); + writeImportPackageSpec((ImportPackageSpecificationImpl) imports[i], out); BundleSpecification[] requiredBundles = bundle.getRequiredBundles(); out.writeInt(requiredBundles.length); @@ -318,7 +319,7 @@ class StateWriter { else { out.writeInt(genericRequires.length); for (int i = 0; i < genericRequires.length; i++) - writeGenericSpecification(genericRequires[i], out); + writeGenericSpecification((GenericSpecificationImpl) genericRequires[i], out); } GenericDescription[] selectedCapabilities = bundle.getSelectedGenericCapabilities(); @@ -360,6 +361,7 @@ class StateWriter { out.writeBoolean(bundle.isExported()); out.writeBoolean(bundle.isOptional()); writeMap(out, bundle.getAttributes()); + writeMap(out, bundle.getArbitraryDirectives()); } private void writeExportPackageDesc(ExportPackageDescriptionImpl exportPackageDesc, DataOutputStream out) throws IOException { @@ -369,6 +371,7 @@ class StateWriter { writeBundleDescription(exportPackageDesc.getExporter(), out, false); writeMap(out, exportPackageDesc.getAttributes()); writeMap(out, exportPackageDesc.getDirectives()); + writeMap(out, exportPackageDesc.getArbitraryDirectives()); writeExportPackageDesc((ExportPackageDescriptionImpl) exportPackageDesc.getFragmentDeclaration(), out); } @@ -390,7 +393,7 @@ class StateWriter { writeGenericDescription((GenericDescription) ((BaseDescriptionImpl) description).getFragmentDeclaration(), out); } - private void writeGenericSpecification(GenericSpecification specification, DataOutputStream out) throws IOException { + private void writeGenericSpecification(GenericSpecificationImpl specification, DataOutputStream out) throws IOException { if (writePrefix(specification, out)) return; writeVersionConstraint(specification, out); @@ -402,6 +405,8 @@ class StateWriter { writeGenericDescription(suppliers[i], out); out.writeInt(specification.getResolution()); writeStringOrNull(specification.getMatchingFilter(), out); + writeMap(out, specification.getAttributes()); + writeMap(out, specification.getArbitraryDirectives()); } private void writeNativeCode(NativeCodeSpecification nativeCodeSpecification, DataOutputStream out) throws IOException { @@ -590,7 +595,7 @@ class StateWriter { writeVersion(rootDesc.getVersion(), out); } - private void writeImportPackageSpec(ImportPackageSpecification importPackageSpec, DataOutputStream out) throws IOException { + private void writeImportPackageSpec(ImportPackageSpecificationImpl importPackageSpec, DataOutputStream out) throws IOException { if (writePrefix(importPackageSpec, out)) return; writeVersionConstraint(importPackageSpec, out); @@ -605,6 +610,7 @@ class StateWriter { writeVersionRange(importPackageSpec.getBundleVersionRange(), out); writeMap(out, importPackageSpec.getAttributes()); writeMap(out, importPackageSpec.getDirectives()); + writeMap(out, importPackageSpec.getArbitraryDirectives()); } private void writeHostSpec(HostSpecificationImpl host, DataOutputStream out, boolean force) throws IOException { @@ -625,6 +631,7 @@ class StateWriter { for (int i = 0; i < hosts.length; i++) writeBundleDescription(hosts[i], out, force); writeMap(out, host.getAttributes()); + writeMap(out, host.getArbitraryDirectives()); } // called by writers for VersionConstraintImpl subclasses diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/VersionConstraintImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/VersionConstraintImpl.java index c7949b792..5a60207f1 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/VersionConstraintImpl.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/VersionConstraintImpl.java @@ -154,7 +154,7 @@ abstract class VersionConstraintImpl implements VersionConstraint { } public String toString() { - return getNamespace() + BaseDescriptionImpl.toString(getAttributes(), false); + return getNamespace() + BaseDescriptionImpl.toString(getAttributes(), false) + BaseDescriptionImpl.toString(getDirectives(), true); } } |