/******************************************************************************* * Copyright (c) 2012, 2015 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 * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.osgi.tests.resource; import java.util.*; import java.util.Map.Entry; import junit.framework.Test; import junit.framework.TestSuite; import org.junit.Assert; import org.osgi.framework.Bundle; import org.osgi.framework.Version; import org.osgi.framework.namespace.IdentityNamespace; import org.osgi.framework.wiring.*; import org.osgi.resource.*; public class BasicTest extends AbstractResourceTest { private interface CapabilityProvider { List getCapabilities(String namespace); } static class BasicCapability implements Capability { private final Map attributes; private final Map directives; private final String namespace; public BasicCapability(String namespace) { this(namespace, Collections.EMPTY_MAP); } public BasicCapability(String namespace, Map attributes) { this(namespace, attributes, Collections.EMPTY_MAP); } public BasicCapability(String namespace, Map attributes, Map directives) { this.namespace = namespace; this.attributes = attributes; this.directives = directives; } public String getNamespace() { return namespace; } public Map getDirectives() { return directives; } public Map getAttributes() { return attributes; } public Resource getResource() { return null; } } private Bundle tb1; private Bundle tb2; private Bundle tb3; private Bundle tb4; private Bundle tf1; private Bundle tf2; public static Test suite() { return new TestSuite(BasicTest.class); } public BasicTest(String name) { super(name); } public void testRequirementMatches() throws Exception { Bundle tb5 = installer.installBundle("resource.tb5"); Resource requirer = tb5.adapt(BundleRevision.class); Capability capability1 = createCapability1(); List requirements = requirer.getRequirements(capability1.getNamespace()); assertRequirements(requirements, 3); Requirement requirement1 = (Requirement) requirements.get(0); // Match requirement with just a namespace (no filter, attributes, or directives). assertRequirementMatches(requirement1, capability1); Capability capability2 = createCapability2(); // Different namespaces should not match. assertNotRequirementMatches(requirement1, capability2); Requirement requirement2 = (Requirement) requirements.get(1); // Make sure the expected attributes are present. assertAttribute(requirement2, "b", "a"); // Match requirement with namespace and attributes. Requirement attributes have no impact on matching. assertRequirementMatches(requirement2, capability1); Requirement requirement3 = (Requirement) requirements.get(2); assertAttribute(requirement3, "b", "a"); assertAttribute(requirement3, "bar", "foo"); assertFilterDirective(requirement3); // Match requirement with namespace, attributes, and filter (no other directives). assertRequirementMatches(requirement3, capability1); Requirement requirement4 = (Requirement) requirements.get(3); assertAttribute(requirement4, "a", "b"); assertFilterDirective(requirement4); // Filters should not match. assertNotRequirementMatches(requirement4, capability1); requirements = requirer.getRequirements(capability2.getNamespace()); assertRequirements(requirements, 0); Requirement requirement5 = (Requirement) requirements.get(0); assertAttribute(requirement5, "bar", "foo"); assertAttribute(requirement5, "y", "x"); assertFilterDirective(requirement5); assertDirective(requirement5, "mandatory", "foo,x"); // Mandatory directive should have no impact on generic capabilities or requirements. assertRequirementMatches(requirement5, capability2); } public void testIdentity() throws Exception { tb1 = installer.installBundle("resource.tb1"); tb2 = installer.installBundle("resource.tb2"); tb3 = installer.installBundle("resource.tb3"); tb4 = installer.installBundle("resource.tb4"); tf1 = installer.installBundle("resource.tf1"); tf2 = installer.installBundle("resource.tf2"); installer.resolveBundles(null); tb1.start(); tb2.start(); tb3.start(); tb4.start(); assertEquals("tf1 not resolved", tf1.getState(), Bundle.RESOLVED); assertEquals("tf2 not resolved", tf2.getState(), Bundle.RESOLVED); assertTb1(); assertTb2(); assertTb3(); assertTb4(); assertTf1(); assertTf2(); } /* * TB1 * Requirements: * None * Capabilities: * osgi.identity;osgi.identity=resource.tb1;version=1.0.0;type=osgi.bundle * osgi.wiring.host;osgi.wiring.host=resource.tb1;version=1.0.0 * Wires: * osgi.identity <-> TB3 * osgi.wiring.host <-> TF1 * TB4 <-> osgi.identity (via TF1) */ private void assertTb1() { // Get the revision for TB1. BundleRevision revision = tb1.adapt(BundleRevision.class); // Make sure TB1's symbolic name and version match the manifest. String symbolicName = revision.getSymbolicName(); assertSymbolicName("resource.tb1", symbolicName); Version version = revision.getVersion(); assertVersion("1.0.0", version); // Make sure TB1's type is correct. String type = getType(revision); assertType(IdentityNamespace.TYPE_BUNDLE, type); Map arbitraryAttrs = new HashMap(); arbitraryAttrs.put("attr1", "a1"); arbitraryAttrs.put("attr2", "a2"); Map arbitraryDirs = new HashMap(); arbitraryDirs.put("dir1", "d1"); arbitraryDirs.put("dir2", "d2"); // Check TB1's osgi.identity capability from the revision. Capability capability = getIdentityCapability(revision); assertIdentityCapability(capability, symbolicName, version, type, arbitraryAttrs, arbitraryDirs); // Check TB1's osgi.identity capability from the resource. Resource resource = revision; capability = getIdentityCapability(resource); assertIdentityCapability(capability, symbolicName, version, type, arbitraryAttrs, arbitraryDirs); // Check TB1's osgi.identity capability from the wiring. BundleWiring wiring = tb1.adapt(BundleWiring.class); capability = getIdentityCapability(wiring); assertIdentityCapability(capability, symbolicName, version, type, arbitraryAttrs, arbitraryDirs); // There should be 1 provided osgi.identity wire (TB1 -> TB3). List wires = wiring.getProvidedWires(IdentityNamespace.IDENTITY_NAMESPACE); assertWires(wires, 1); // Check the osgi.identity wire between TB1 and TB3. Wire wire = (Wire) wires.get(0); BundleRevision requirer = tb3.adapt(BundleRevision.class); Requirement requirement = getIdentityRequirement(requirer, 1); assertIdentityWire(wire, capability, revision, requirement, requirer); // There should be 1 required osgi.identity wire (TB4 -> TB1 via TF1). wires = wiring.getRequiredWires(IdentityNamespace.IDENTITY_NAMESPACE); assertWires(wires, 1); // Check the osgi.identity wire between TB4 and TB1 (via TF1). wire = (Wire) wires.get(0); BundleRevision provider = tb4.adapt(BundleRevision.class); capability = getIdentityCapability(provider); requirement = getIdentityRequirement(tf1.adapt(BundleRevision.class), 0); assertIdentityWire(wire, capability, provider, requirement, revision); } /* * TB2 * Requirements: * None * Capabilities: * None * Wires: * None */ private void assertTb2() { final BundleRevision revision = tb2.adapt(BundleRevision.class); assertNotIdentityCapability(new CapabilityProvider() { public List getCapabilities(String namespace) { return revision.getDeclaredCapabilities(namespace); } }); final Resource resource = revision; assertNotIdentityCapability(new CapabilityProvider() { public List getCapabilities(String namespace) { return resource.getCapabilities(namespace); } }); final BundleWiring wiring = tb2.adapt(BundleWiring.class); assertNotIdentityCapability(new CapabilityProvider() { public List getCapabilities(String namespace) { return wiring.getCapabilities(namespace); } }); } /* * TB3 * Requirements: * osgi.identity;osgi.identity=resource.tb1;version=1.0.0;type=osgi.bundle * osgi.identity;osgi.identity=resource.tf1;version=1.0.0;type=osgi.fragment * Capabilities: * osgi.identity;osgi.identity=resource.tb3;version=1.0.0;type=osgi.bundle * osgi.wiring.host;osgi.wiring.host=resource.tb3;version=1.0.0 * Wires: * TB1 <-> osgi.identity * TF1 <-> osgi.identity */ private void assertTb3() { // Get the revision for TB3. BundleRevision revision = tb3.adapt(BundleRevision.class); // Make sure TB3's symbolic name and version match the manifest. String symbolicName = revision.getSymbolicName(); assertSymbolicName("resource.tb3", symbolicName); Version version = revision.getVersion(); assertVersion("1.0.0", version); // Make sure TB3's type is correct. String type = getType(revision); assertType(IdentityNamespace.TYPE_BUNDLE, type); // Check TB3's osgi.identity capability from the revision. Capability capability = getIdentityCapability(revision); assertIdentityCapability(capability, symbolicName, version, type, Collections.EMPTY_MAP, Collections.EMPTY_MAP); Resource resource = revision; // Check TB3's osgi.identity capability from the resource. capability = getIdentityCapability(resource); assertIdentityCapability(capability, symbolicName, version, type, Collections.EMPTY_MAP, Collections.EMPTY_MAP); // Check TB3's osgi.identity capability from the wiring. BundleWiring wiring = tb3.adapt(BundleWiring.class); capability = getIdentityCapability(wiring); assertIdentityCapability(capability, symbolicName, version, type, Collections.EMPTY_MAP, Collections.EMPTY_MAP); // There should be 2 required osgi.identity wires (TB1 -> TB3 and TF1 -> TB3). List wires = wiring.getRequiredWires(IdentityNamespace.IDENTITY_NAMESPACE); assertWires(wires, 2); // Check the osgi.identity wire between TB1 and TB3. Wire wire = (Wire) wires.get(1); Requirement requirement = getIdentityRequirement(revision, 1); BundleRevision provider = tb1.adapt(BundleRevision.class); capability = getIdentityCapability(provider); assertIdentityWire(wire, capability, provider, requirement, revision); // Check the osgi.identity wire between TF1 and TB3. wire = (Wire) wires.get(0); requirement = getIdentityRequirement(revision, 0); provider = tf1.adapt(BundleRevision.class); capability = getIdentityCapability(provider); assertIdentityWire(wire, capability, provider, requirement, revision); } /* * TB4 * Requirements: * None * Capabilities: * osgi.identity;osgi.identity=resource.tb4;version=1.0.0;type=osgi.bundle * osgi.wiring.host;osgi.wiring.host=resource.tb4;version=1.0.0 * Wires: * osgi.identity <-> TB1 (via TF1) */ private void assertTb4() { // Get the revision for TB4. BundleRevision revision = tb4.adapt(BundleRevision.class); // Make sure TB4's symbolic name and version match the manifest. String symbolicName = revision.getSymbolicName(); assertSymbolicName("resource.tb4", symbolicName); Version version = revision.getVersion(); assertVersion("1.0.0", version); // Make sure TB4's type is correct. String type = getType(revision); assertType(IdentityNamespace.TYPE_BUNDLE, type); // Check TB4's osgi.identity capability from the revision. Capability capability = getIdentityCapability(revision); assertIdentityCapability(capability, symbolicName, version, type, Collections.EMPTY_MAP, Collections.EMPTY_MAP); Resource resource = revision; // Check TB4's osgi.identity capability from the resource. capability = getIdentityCapability(resource); assertIdentityCapability(capability, symbolicName, version, type, Collections.EMPTY_MAP, Collections.EMPTY_MAP); BundleWiring wiring = tb4.adapt(BundleWiring.class); // Check TB4's osgi.identity capability from the wiring. capability = getIdentityCapability(wiring); assertIdentityCapability(capability, symbolicName, version, type, Collections.EMPTY_MAP, Collections.EMPTY_MAP); // There should be 1 provided osgi.identity wire (TB4 -> TB1 via TF1). List wires = wiring.getProvidedWires(IdentityNamespace.IDENTITY_NAMESPACE); assertWires(wires, 1); // Check the osgi.identity wire between TB4 and TB1 (via TF1). Wire wire = (Wire) wires.get(0); // The requirer will be TB1's revision since fragment requirements are merged into the host... BundleRevision requirer = tb1.adapt(BundleRevision.class); // ...but the requirement will come from the fragment. Requirement requirement = getIdentityRequirement(tf1.adapt(BundleRevision.class), 0); assertIdentityWire(wire, capability, revision, requirement, requirer); } /* * TF1 * Requirements: * osgi.wiring.host;osgi.wiring.host=resource.tb1;version=1.0.0 * osgi.identity;osgi.identity=resource.tb4;version=1.0.0;type=osgi.bundle * Capabilities: * osgi.identity;osgi.identity=resource.tf1;version=1.0.0;type=osgi.fragment * Wires: * TB1 <-> osgi.wiring.host * osgi.identity <-> TB3 */ private void assertTf1() { // Get the revision for TF1. BundleRevision revision = tf1.adapt(BundleRevision.class); // Make sure TF1's symbolic name and version match the manifest. String symbolicName = revision.getSymbolicName(); assertSymbolicName("resource.tf1", symbolicName); Version version = revision.getVersion(); assertVersion("1.0.0", version); // Make sure TF1's type is correct. String type = getType(revision); assertType(IdentityNamespace.TYPE_FRAGMENT, type); // Check TF1's osgi.identity capability from the revision. Capability capability = getIdentityCapability(revision); assertIdentityCapability(capability, symbolicName, version, type, Collections.EMPTY_MAP, Collections.EMPTY_MAP); // Check TF1's osgi.identity capability from the resource. Resource resource = revision; capability = getIdentityCapability(resource); assertIdentityCapability(capability, symbolicName, version, type, Collections.EMPTY_MAP, Collections.EMPTY_MAP); // Check TF1's osgi.identity capability from the wiring. BundleWiring wiring = tf1.adapt(BundleWiring.class); capability = getIdentityCapability(wiring); assertIdentityCapability(capability, symbolicName, version, type, Collections.EMPTY_MAP, Collections.EMPTY_MAP); // There should be 1 provided osgi.identity wire (TF1 -> TB3). List wires = wiring.getProvidedWires(IdentityNamespace.IDENTITY_NAMESPACE); assertWires(wires, 1); // Check the osgi.identity wire between TF1 and TB3. Wire wire = (Wire) wires.get(0); BundleRevision requirer = tb3.adapt(BundleRevision.class); Requirement requirement = getIdentityRequirement(requirer, 0); assertIdentityWire(wire, capability, revision, requirement, requirer); } /* * TF2 * Requirements: * osgi.wiring.host;osgi.wiring.host=resource.tb1;version=1.0.0 * Capabilities: * osgi.identity;osgi.identity=resource.tf2;version=1.0.0;type=osgi.fragment * Wires: * TB1 <-> osgi.wiring.host */ private void assertTf2() { // Get the revision for TF2. BundleRevision revision = tf2.adapt(BundleRevision.class); // Make sure TF1's symbolic name and version match the manifest. String symbolicName = revision.getSymbolicName(); assertSymbolicName("resource.tf2", symbolicName); Version version = revision.getVersion(); assertVersion("0.0.0", version); // Make sure TF1's type is correct. String type = getType(revision); assertType(IdentityNamespace.TYPE_FRAGMENT, type); // Check TF1's osgi.identity capability from the revision. Capability capability = getIdentityCapability(revision); assertIdentityCapability(capability, symbolicName, version, type, Collections.EMPTY_MAP, Collections.EMPTY_MAP); // Check TF1's osgi.identity capability from the resource. Resource resource = revision; capability = getIdentityCapability(resource); assertIdentityCapability(capability, symbolicName, version, type, Collections.EMPTY_MAP, Collections.EMPTY_MAP); // Check TF1's osgi.identity capability from the wiring. BundleWiring wiring = tf2.adapt(BundleWiring.class); capability = getIdentityCapability(wiring); assertIdentityCapability(capability, symbolicName, version, type, Collections.EMPTY_MAP, Collections.EMPTY_MAP); // There should be 0 provided osgi.identity wire (TF1 -> TB3). List wires = wiring.getProvidedWires(IdentityNamespace.IDENTITY_NAMESPACE); assertWires(wires, 0); } private void assertAttribute(Requirement requirement, String name, Object expected) { assertEquals("Wrong attribute: " + name, expected, requirement.getAttributes().get(name)); } private void assertCapabilities(List capabilities, int size) { assertNotNull("Null capabilities", capabilities); assertEquals("Wrong number of capabilities", size, capabilities.size()); } private void assertDirective(Requirement requirement, String name, String expected) { assertEquals("Wrong directive", expected, requirement.getDirectives().get(name)); } private void assertFilterDirective(Requirement requirement) { assertNotNull("Missing filter directive", requirement.getDirectives().get(Namespace.REQUIREMENT_FILTER_DIRECTIVE)); } private void assertIdentityCapability(Capability capability, String symbolicName, Version version, String type, Map arbitraryAttrs, Map arbitraryDirs) { assertEquals("Wrong namespace", IdentityNamespace.IDENTITY_NAMESPACE, capability.getNamespace()); assertEquals("Wrong number of attributes", 3 + arbitraryAttrs.size(), capability.getAttributes().size()); // The osgi.identity attribute contains the symbolic name of the resource. assertSymbolicName(symbolicName, (String) capability.getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE)); // The version attribute must be of type Version. // The version attribute contains the version of the resource. assertVersion(version, (Version) capability.getAttributes().get(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE)); // The type attribute must be of type String. // The type attribute contains the resource type. assertType(type, (String) capability.getAttributes().get(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE)); Map attributes = capability.getAttributes(); for (Iterator iEntries = arbitraryAttrs.entrySet().iterator(); iEntries.hasNext();) { Map.Entry entry = (Entry) iEntries.next(); assertEquals("Wrong attribute: " + entry.getKey(), entry.getValue(), attributes.get(entry.getKey())); } Map directives = capability.getDirectives(); for (Iterator iEntries = arbitraryDirs.entrySet().iterator(); iEntries.hasNext();) { Map.Entry entry = (Entry) iEntries.next(); assertEquals("Wrong directive: " + entry.getKey(), entry.getValue(), directives.get(entry.getKey())); } } private void assertIdentityWire(Wire wire, Capability capability, Resource provider, Requirement requirement, Resource requirer) { assertEquals("Wrong capability", capability, wire.getCapability()); assertEquals("Wrong provider", provider, wire.getProvider()); assertEquals("Wrong requirement", requirement, wire.getRequirement()); assertEquals("Wrong requirer", requirer, wire.getRequirer()); assertRequirementMatches(requirement, capability); } private void assertNotIdentityCapability(CapabilityProvider provider) { List capabilities = provider.getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE); // A resource with no symbolic name must not provide an identity capability. assertCapabilities(capabilities, 0); } private void assertNotRequirementMatches(Requirement requirement, Capability capability) { if (!(requirement instanceof BundleRequirement) || !(capability instanceof BundleCapability)) return; assertFalse("Requirement matches capability", ((BundleRequirement) requirement).matches((BundleCapability) capability)); } private void assertNotNull(Capability capability) { Assert.assertNotNull("Null capability", capability); } private void assertNotNull(Requirement requirement) { Assert.assertNotNull("Null requirement", requirement); } private void assertRequirementMatches(Requirement requirement, Capability capability) { if (!(requirement instanceof BundleRequirement) || !(capability instanceof BundleCapability)) return; assertTrue("Requirement does not match capability", ((BundleRequirement) requirement).matches((BundleCapability) capability)); } private void assertRequirements(List requirements, int index) { assertNotNull("Null requirements", requirements); assertTrue("Wrong number of requirements", requirements.size() > index); } private void assertSymbolicName(String expected, String actual) { assertEquals("Wrong symbolic name", expected, actual); } private void assertType(String expected, String actual) { assertEquals("Wrong type", expected, actual); } private void assertVersion(String expected, Version actual) { assertVersion(Version.parseVersion(expected), actual); } private void assertVersion(Version expected, Version actual) { assertEquals("Wrong version", expected, actual); } private void assertWires(List wires, int size) { assertNotNull("Null wires", wires); assertEquals("Wrong number of wires", size, wires.size()); } private Capability createCapability1() { String namespace = "capability.1"; Map attributes = new HashMap(); attributes.put("a", "b"); return new BasicCapability(namespace, attributes); } private Capability createCapability2() { String namespace = "capability.2"; Map attributes = new HashMap(); attributes.put("foo", "bar"); attributes.put("x", "y"); Map directives = new HashMap(); directives.put(Namespace.RESOLUTION_MANDATORY, "foo,x"); return new BasicCapability(namespace, attributes, directives); } private Capability getIdentityCapability(BundleRevision revision) { List capabilities = revision.getDeclaredCapabilities(IdentityNamespace.IDENTITY_NAMESPACE); assertCapabilities(capabilities, 1); Capability capability = (Capability) capabilities.get(0); assertNotNull(capability); return capability; } private Capability getIdentityCapability(BundleWiring wiring) { List capabilities = wiring.getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE); assertCapabilities(capabilities, 1); Capability capability = (Capability) capabilities.get(0); assertNotNull(capability); return capability; } private Capability getIdentityCapability(Resource resource) { List capabilities = resource.getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE); assertCapabilities(capabilities, 1); Capability capability = (Capability) capabilities.get(0); assertNotNull(capability); return capability; } private Requirement getIdentityRequirement(BundleRevision revision, int index) { List requirements = revision.getDeclaredRequirements(IdentityNamespace.IDENTITY_NAMESPACE); assertRequirements(requirements, index); Requirement requirement = (Requirement) requirements.get(index); assertNotNull(requirement); return requirement; } private String getType(BundleRevision revision) { return (revision.getTypes() & BundleRevision.TYPE_FRAGMENT) == 0 ? IdentityNamespace.TYPE_BUNDLE : IdentityNamespace.TYPE_FRAGMENT; } }