You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by jw...@apache.org on 2012/11/28 17:41:30 UTC
svn commit: r1414804 - in /aries/trunk/subsystem:
subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/
subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/
Author: jwross
Date: Wed Nov 28 16:41:29 2012
New Revision: 1414804
URL: http://svn.apache.org/viewvc?rev=1414804&view=rev
Log:
[ARIES-968] Consider using a "multiple attempts" strategy versus the current locking strategy when updating sharing policies.
The synchronization has been replaced with a retry strategy. If the region digraph fails to replace because something else
modified it after the copy was made, up to 9 additional attempts will be made, for a total of 10. This has the advantage of
avoiding a bottleneck as well as protecting against modifications from actors other than subsystems. If replacement still
fails after the 10th attempt, a SubsystemException is thrown.
Also created a more robust test for adding requirements. This required some fixes to the copy/replace algorithm in order to
account for bundle ids and child connections.
Modified:
aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BasicSubsystem.java
aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/AriesSubsystemTest.java
aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/SubsystemTest.java
Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BasicSubsystem.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BasicSubsystem.java?rev=1414804&r1=1414803&r2=1414804&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BasicSubsystem.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BasicSubsystem.java Wed Nov 28 16:41:29 2012
@@ -24,11 +24,13 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Set;
import org.apache.aries.subsystem.AriesSubsystem;
import org.apache.aries.subsystem.core.archive.AriesSubsystemParentsHeader;
@@ -552,47 +554,86 @@ public class BasicSubsystem implements R
// Unscoped subsystems import everything.already.
if (!isScoped())
return;
- Region currentRegion = getRegion();
- RegionDigraph currentDigraph = currentRegion.getRegionDigraph();
- RegionFilterBuilder filterBuilder = currentDigraph.createRegionFilterBuilder();
- try {
- // Copy the sharing policy of the current region.
- for (FilteredRegion filteredRegion : currentRegion.getEdges()) {
- Map<String, Collection<String>> sharingPolicy = filteredRegion.getFilter().getSharingPolicy();
- for (Map.Entry<String, Collection<String>> entry : sharingPolicy.entrySet())
- for (String filter : entry.getValue())
- filterBuilder.allow(entry.getKey(), filter);
- }
- // Add the additional requirements to the sharing policy.
- for (Requirement requirement : requirements) {
- String namespace = requirement.getNamespace();
- // The osgi.service namespace requires translation.
- if (ServiceNamespace.SERVICE_NAMESPACE.equals(namespace))
- namespace = RegionFilter.VISIBLE_SERVICE_NAMESPACE;
- String filter = requirement.getDirectives().get(IdentityNamespace.REQUIREMENT_FILTER_DIRECTIVE);
- // A null filter means import everything from that namespace.
- if (filter == null)
- filterBuilder.allowAll(namespace);
- else
- filterBuilder.allow(namespace, filter);
- }
- // Update the region digraph. Lock on the class to prevent conflicts
- // with other subsystems updating their own requirements.
- // TODO This lock does not prevent conflicts with users outside of
- // subsystems.
- synchronized (BasicSubsystem.class) {
+ for (int i = 0; i < 10; i++) {
+ try {
+ Region oldRegion = getRegion();
+ RegionDigraph currentDigraph = oldRegion.getRegionDigraph();
RegionDigraph copiedDigraph = currentDigraph.copy();
- copiedDigraph.removeRegion(currentRegion);
- Region fromRegion = copiedDigraph.createRegion(currentRegion.getName());
- Region toRegion = ((BasicSubsystem)getParents().iterator().next()).getRegion();
- copiedDigraph.connect(fromRegion, filterBuilder.build(), copiedDigraph.getRegion(toRegion.getName()));
- // TODO Protect against the possibility of an already modified
- // digraph with multiple attempts, if necessary?
- currentDigraph.replace(copiedDigraph);
+ Region newRegion = copiedDigraph.getRegion(oldRegion.getName());
+ // Store the bundle ids for future reference.
+ Set<Long> bundleIds = newRegion.getBundleIds();
+ // Store the current connection info with parent for future reference.
+ RegionFilterBuilder parentFilter = copiedDigraph.createRegionFilterBuilder();
+ for (FilteredRegion filteredRegion : newRegion.getEdges()) {
+ Map<String, Collection<String>> sharingPolicy = filteredRegion.getFilter().getSharingPolicy();
+ for (Map.Entry<String, Collection<String>> entry : sharingPolicy.entrySet())
+ for (String filter : entry.getValue())
+ parentFilter.allow(entry.getKey(), filter);
+ }
+ // Add the additional requirements to the connection info with parent.
+ for (Requirement requirement : requirements) {
+ String namespace = requirement.getNamespace();
+ // The osgi.service namespace requires translation.
+ if (ServiceNamespace.SERVICE_NAMESPACE.equals(namespace))
+ namespace = RegionFilter.VISIBLE_SERVICE_NAMESPACE;
+ String filter = requirement.getDirectives().get(IdentityNamespace.REQUIREMENT_FILTER_DIRECTIVE);
+ // A null filter means import everything from that namespace.
+ if (filter == null)
+ parentFilter.allowAll(namespace);
+ else
+ parentFilter.allow(namespace, filter);
+ }
+ // Store the connection info with children for future reference.
+ Map<String, RegionFilterBuilder> childFilters = new HashMap<String, RegionFilterBuilder>();
+ for (Subsystem child : getChildren()) {
+ if (!((BasicSubsystem)child).isScoped())
+ continue;
+ Region childRegion = ((BasicSubsystem)child).getRegion();
+ RegionFilterBuilder childBuilder = copiedDigraph.createRegionFilterBuilder();
+ for (FilteredRegion filteredRegion : childRegion.getEdges()) {
+ Map<String, Collection<String>> sharingPolicy = filteredRegion.getFilter().getSharingPolicy();
+ for (Map.Entry<String, Collection<String>> entry : sharingPolicy.entrySet())
+ for (String filter : entry.getValue())
+ childBuilder.allow(entry.getKey(), filter);
+ }
+ childFilters.put(childRegion.getName(), childBuilder);
+ }
+ // Remove the region so the parent connection can be updated.
+ copiedDigraph.removeRegion(newRegion);
+ // Recreate the region.
+ newRegion = copiedDigraph.createRegion(newRegion.getName());
+ // Copy the bundle ids.
+ for (Long bundleId : bundleIds)
+ newRegion.addBundle(bundleId);
+ // Reconnect to the parent.
+ copiedDigraph.connect(newRegion, parentFilter.build(), copiedDigraph.getRegion(((BasicSubsystem)getParents().iterator().next()).getRegion().getName()));
+ // Reconnect the children.
+ for (Map.Entry<String, RegionFilterBuilder> entry : childFilters.entrySet())
+ copiedDigraph.connect(copiedDigraph.getRegion(entry.getKey()), entry.getValue().build(), newRegion);
+ // Replace the current digraph.
+ try {
+ currentDigraph.replace(copiedDigraph);
+ }
+ catch (BundleException e) {
+ // Something modified digraph since the copy was made.
+ if (i < 10)
+ // There are more attempts to make.
+ continue;
+ // Number of attempts has been exhausted.
+ throw e;
+ }
+ // Success! No need to continue looping.
+ break;
+ }
+ // If an exception occurs for any reason other than a replacement
+ // failure, or replacement failed with no more attempts left, break
+ // out of the loop and throw it.
+ catch (SubsystemException e) {
+ throw e;
+ }
+ catch (Exception e) {
+ throw new SubsystemException(e);
}
- }
- catch (Exception e) {
- throw new SubsystemException(e);
}
}
Modified: aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/AriesSubsystemTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/AriesSubsystemTest.java?rev=1414804&r1=1414803&r2=1414804&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/AriesSubsystemTest.java (original)
+++ aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/AriesSubsystemTest.java Wed Nov 28 16:41:29 2012
@@ -1,5 +1,6 @@
package org.apache.aries.subsystem.itests;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.fail;
@@ -18,6 +19,9 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.junit.MavenConfiguredJUnit4TestRunner;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Version;
+import org.osgi.framework.namespace.IdentityNamespace;
import org.osgi.framework.namespace.PackageNamespace;
import org.osgi.resource.Requirement;
import org.osgi.resource.Resource;
@@ -25,8 +29,6 @@ import org.osgi.service.subsystem.Subsys
import org.osgi.service.subsystem.SubsystemConstants;
import org.osgi.service.subsystem.SubsystemException;
-import aQute.lib.osgi.Constants;
-
@RunWith(MavenConfiguredJUnit4TestRunner.class)
public class AriesSubsystemTest extends SubsystemTest {
/*
@@ -35,11 +37,21 @@ public class AriesSubsystemTest extends
*/
private static final String APPLICATION_A = "application.a.esa";
/*
+ * Subsystem-SymbolicName: application.b.esa
+ * Subsystem-Content: bundle.b.jar
+ */
+ private static final String APPLICATION_B = "application.b.esa";
+ /*
* Bundle-SymbolicName: bundle.a.jar
* Import-Package: org.osgi.framework,org.osgi.resource
*/
private static final String BUNDLE_A = "bundle.a.jar";
/*
+ * Bundle-SymbolicName: bundle.b.jar
+ * Import-Package: org.osgi.resource
+ */
+ private static final String BUNDLE_B = "bundle.b.jar";
+ /*
* Subsystem-SymbolicName: composite.a.esa
* Subsystem-Type: osgi.subsystem.composite
*/
@@ -50,27 +62,47 @@ public class AriesSubsystemTest extends
createSubsystem(APPLICATION_A, BUNDLE_A);
}
+ private static void createApplicationB() throws IOException {
+ createApplicationBManifest();
+ createSubsystem(APPLICATION_B, BUNDLE_B);
+ }
+
private static void createApplicationAManifest() throws IOException {
Map<String, String> attributes = new HashMap<String, String>();
attributes.put(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME, APPLICATION_A);
createManifest(APPLICATION_A + ".mf", attributes);
}
+ private static void createApplicationBManifest() throws IOException {
+ Map<String, String> attributes = new HashMap<String, String>();
+ attributes.put(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME, APPLICATION_B);
+ createManifest(APPLICATION_B + ".mf", attributes);
+ }
+
private static void createBundleA() throws IOException {
Map<String, String> headers = new HashMap<String, String>();
headers.put(Constants.IMPORT_PACKAGE, "org.osgi.framework,org.osgi.resource");
createBundle(BUNDLE_A, headers);
}
+ private static void createBundleB() throws IOException {
+ Map<String, String> headers = new HashMap<String, String>();
+ headers.put(Constants.IMPORT_PACKAGE, "org.osgi.resource");
+ createBundle(BUNDLE_B, headers);
+ }
+
private static void createCompositeA() throws IOException {
createCompositeAManifest();
- createSubsystem(COMPOSITE_A);
+ createSubsystem(COMPOSITE_A, BUNDLE_B, APPLICATION_B);
}
private static void createCompositeAManifest() throws IOException {
Map<String, String> attributes = new HashMap<String, String>();
attributes.put(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME, COMPOSITE_A);
attributes.put(SubsystemConstants.SUBSYSTEM_TYPE, SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE);
+ attributes.put(SubsystemConstants.SUBSYSTEM_CONTENT,
+ BUNDLE_B + ';' + IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE + "=\"[0,0]\","
+ + APPLICATION_B + ';' + IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE + "=\"[0,0]\";" + IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE + '=' + SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION);
attributes.put(Constants.IMPORT_PACKAGE, "org.osgi.resource");
createManifest(COMPOSITE_A + ".mf", attributes);
}
@@ -81,7 +113,9 @@ public class AriesSubsystemTest extends
if (createdTestFiles)
return;
createBundleA();
+ createBundleB();
createApplicationA();
+ createApplicationB();
createCompositeA();
createdTestFiles = true;
}
@@ -90,31 +124,62 @@ public class AriesSubsystemTest extends
super.setUp();
}
+ /*
+ * Test the AriesSubsystem.addRequirements(Collection<Requirement>) method.
+ *
+ * There are several things to consider for this test.
+ *
+ * (1) Installing a child subsystem before the requirement has been added
+ * should fail.
+ * (2) Installing a child subsystem after the requirement has been added
+ * should succeed.
+ * (3) The newly created region should contain all of the bundles from the
+ * old one.
+ * (4) The connections between the subsystem with the added requirement and
+ * its parents should be reestablished.
+ * (5) The connections between the subsystem with the added requirement and
+ * its children should be reestablished.
+ */
@Test
public void testAddRequirements() throws Exception {
- Subsystem compositeA = installSubsystemFromFile(COMPOSITE_A);
+ AriesSubsystem compositeA = (AriesSubsystem)installSubsystemFromFile(COMPOSITE_A);
try {
+ startSubsystem(compositeA);
+ assertCompositeABefore(compositeA);
+ // Test that the installation of applicationA fails.
try {
installSubsystemFromFile(compositeA, APPLICATION_A);
- fail("Subsystem should not have installed");
+ fail("Subsystem should not have installed due to unresolved org.osgi.framework package requirement");
} catch (SubsystemException e) {
// Okay.
}
+ // Add the org.osgi.framework package requirement.
Requirement requirement = new BasicRequirement.Builder()
- .namespace(PackageNamespace.PACKAGE_NAMESPACE)
- .directive(
- PackageNamespace.REQUIREMENT_FILTER_DIRECTIVE,
- "(osgi.wiring.package=org.osgi.framework)")
+ .namespace(PackageNamespace.PACKAGE_NAMESPACE)
+ .directive(
+ PackageNamespace.REQUIREMENT_FILTER_DIRECTIVE,
+ "(osgi.wiring.package=org.osgi.framework)")
.resource(EasyMock.createMock(Resource.class))
.build();
- ((AriesSubsystem)compositeA).addRequirements(Collections.singleton(requirement));
+ compositeA.addRequirements(Collections.singleton(requirement));
+ // Test that the bundles were copied over to the newly created region.
+ assertCompositeABefore(compositeA);
+ // Test that the parent connections were reestablished.
+ assertRefreshAndResolve(Collections.singletonList(getConstituentAsBundle(compositeA, BUNDLE_B, null, null)));
+ // Test that the child connections were reestablished.
+ assertRefreshAndResolve(Collections.singletonList(getConstituentAsBundle(getConstituentAsSubsystem(compositeA, APPLICATION_B, null, SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION), BUNDLE_B, null, null)));
+ // Test that the installation of applicationA succeeds.
+ AriesSubsystem applicationA;
try {
- installSubsystemFromFile(compositeA, APPLICATION_A);
+ applicationA = (AriesSubsystem)installSubsystemFromFile(compositeA, APPLICATION_A);
+ startSubsystem(applicationA);
} catch (SubsystemException e) {
- fail("Subsystem should have installed");
+ fail("Subsystem should have installed and started");
}
- } finally {
- uninstallSubsystemSilently(compositeA);
+ assertCompositeAAfter(compositeA);
+ }
+ finally {
+ stopAndUninstallSubsystemSilently(compositeA);
}
}
@@ -149,4 +214,47 @@ public class AriesSubsystemTest extends
}
assertSame("Services should be the same instance", root1, root2);
}
+
+ private void assertCompositeAAfter(Subsystem compositeA) {
+ // applicationA, applicationB, bundleB, region context bundle
+ assertConstituents(4, compositeA);
+ assertConstituent(compositeA, APPLICATION_A, null, SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION);
+ assertConstituent(compositeA, APPLICATION_B, null, SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION);
+ assertConstituent(compositeA, BUNDLE_B);
+ assertNotNull("Bundle not in region", getRegion(compositeA).getBundle(BUNDLE_B, Version.emptyVersion));
+ assertConstituent(compositeA, "org.osgi.service.subsystem.region.context.1", Version.parseVersion("1"));
+ // applicationA, applicationB
+ assertChildren(2, compositeA);
+ assertApplicationA(assertChild(compositeA, APPLICATION_A));
+ assertApplicationB(assertChild(compositeA, APPLICATION_B));
+ }
+
+ private void assertCompositeABefore(Subsystem compositeA) {
+ // applicationB, bundleB, region context bundle
+ assertConstituents(3, compositeA);
+ assertConstituent(compositeA, APPLICATION_B, null, SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION);
+ assertConstituent(compositeA, BUNDLE_B);
+ assertNotNull("Bundle not in region", getRegion(compositeA).getBundle(BUNDLE_B, Version.emptyVersion));
+ assertConstituent(compositeA, "org.osgi.service.subsystem.region.context.1", Version.parseVersion("1"));
+ // applicationB
+ assertChildren(1, compositeA);
+ assertApplicationB(assertChild(compositeA, APPLICATION_B));
+ }
+
+ private void assertApplicationA(Subsystem applicationA) {
+ // bundleA, region context bundle
+ assertConstituents(2, applicationA);
+ assertConstituent(applicationA, BUNDLE_A);
+ // The subsystem id is 4 instead of 3 due to the first installation that failed.
+ assertConstituent(applicationA, "org.osgi.service.subsystem.region.context.4", Version.parseVersion("1"));
+ assertChildren(0, applicationA);
+ }
+
+ private void assertApplicationB(Subsystem applicationB) {
+ // bundleB, region context bundle
+ assertConstituents(2, applicationB);
+ assertConstituent(applicationB, BUNDLE_B);
+ assertConstituent(applicationB, "org.osgi.service.subsystem.region.context.2", Version.parseVersion("1"));
+ assertChildren(0, applicationB);
+ }
}
Modified: aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/SubsystemTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/SubsystemTest.java?rev=1414804&r1=1414803&r2=1414804&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/SubsystemTest.java (original)
+++ aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/SubsystemTest.java Wed Nov 28 16:41:29 2012
@@ -38,6 +38,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.aries.subsystem.AriesSubsystem;
import org.apache.aries.subsystem.core.archive.ProvisionPolicyDirective;
@@ -60,6 +61,8 @@ import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
+import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.FrameworkListener;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
@@ -69,6 +72,7 @@ import org.osgi.framework.namespace.Iden
import org.osgi.framework.startlevel.BundleStartLevel;
import org.osgi.framework.startlevel.FrameworkStartLevel;
import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.FrameworkWiring;
import org.osgi.resource.Resource;
import org.osgi.service.repository.Repository;
import org.osgi.service.repository.RepositoryContent;
@@ -250,6 +254,20 @@ public abstract class SubsystemTest exte
assertTrue("Wrong state: " + bundle + " [expected " + state + " but was " + bundle.getState() + "]", (bundle.getState() & state) != 0);
}
+ protected Subsystem assertChild(Subsystem parent, String symbolicName) {
+ return assertChild(parent, symbolicName, null, null);
+ }
+
+ protected Subsystem assertChild(Subsystem parent, String symbolicName, Version version) {
+ return assertChild(parent, symbolicName, version, null);
+ }
+
+ protected Subsystem assertChild(Subsystem parent, String symbolicName, Version version, String type) {
+ Subsystem result = getChild(parent, symbolicName, version, type);
+ assertNotNull("Child does not exist: " + symbolicName, result);
+ return result;
+ }
+
protected void assertChild(Subsystem parent, Subsystem child) {
Collection<Subsystem> children = new ArrayList<Subsystem>(1);
children.add(child);
@@ -397,6 +415,31 @@ public abstract class SubsystemTest exte
assertTrue("Subsystem accepts dependencies", directive.isRejectDependencies());
}
+ protected void assertRefresh(Collection<Bundle> bundles) throws InterruptedException {
+ FrameworkWiring wiring = getSystemBundleAsFrameworkWiring();
+ final AtomicBoolean refreshed = new AtomicBoolean(false);
+ wiring.refreshBundles(bundles, new FrameworkListener() {
+ @Override
+ public void frameworkEvent(FrameworkEvent event) {
+ if (FrameworkEvent.PACKAGES_REFRESHED == event.getType()) {
+ synchronized (refreshed) {
+ refreshed.set(true);
+ refreshed.notify();
+ }
+ }
+ }
+ });
+ synchronized (refreshed) {
+ refreshed.wait(5000);
+ }
+ assertTrue("Bundles not refreshed", refreshed.get());
+ }
+
+ protected void assertRefreshAndResolve(Collection<Bundle> bundles) throws InterruptedException {
+ assertRefresh(bundles);
+ assertResolve(bundles);
+ }
+
protected void assertRegionContextBundle(Subsystem s) {
Bundle b = getRegionContextBundle(s);
assertEquals("Not active", Bundle.ACTIVE, b.getState());
@@ -406,6 +449,11 @@ public abstract class SubsystemTest exte
assertConstituent(s, "org.osgi.service.subsystem.region.context." + s.getSubsystemId(), Version.parseVersion("1.0.0"), IdentityNamespace.TYPE_BUNDLE);
}
+ protected void assertResolve(Collection<Bundle> bundles) {
+ FrameworkWiring wiring = getSystemBundleAsFrameworkWiring();
+ assertTrue("Bundles not resolved", wiring.resolveBundles(bundles));
+ }
+
protected void assertServiceEventsInstall(Subsystem subsystem) throws InterruptedException {
assertEvent(subsystem, Subsystem.State.INSTALLING, subsystemEvents.poll(subsystem.getSubsystemId(), 5000));
assertEvent(subsystem, Subsystem.State.INSTALLED, subsystemEvents.poll(subsystem.getSubsystemId(), 5000));
@@ -584,6 +632,31 @@ public abstract class SubsystemTest exte
return null;
}
+ protected Subsystem getChild(Subsystem parent, String symbolicName) {
+ return getChild(parent, symbolicName, null, null);
+ }
+
+ protected Subsystem getChild(Subsystem parent, String symbolicName, Version version) {
+ return getChild(parent, symbolicName, version, null);
+ }
+
+ protected Subsystem getChild(Subsystem parent, String symbolicName, Version version, String type) {
+ for (Subsystem child : parent.getChildren()) {
+ if (symbolicName.equals(child.getSymbolicName())) {
+ if (version == null)
+ version = Version.emptyVersion;
+ if (version.equals(child.getVersion())) {
+ if (type == null)
+ type = SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION;
+ if (type.equals(child.getType())) {
+ return child;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
protected Resource getConstituent(Subsystem subsystem, String symbolicName, Version version, String type) {
for (Resource resource : subsystem.getConstituents()) {
if (symbolicName.equals(ResourceHelper.getSymbolicNameAttribute(resource))) {
@@ -601,6 +674,11 @@ public abstract class SubsystemTest exte
return null;
}
+ protected AriesSubsystem getConstituentAsAriesSubsystem(Subsystem subsystem, String symbolicName, Version version, String type) {
+ Resource resource = getConstituent(subsystem, symbolicName, version, type);
+ return (AriesSubsystem)resource;
+ }
+
protected Bundle getConstituentAsBundle(Subsystem subsystem, String symbolicName, Version version, String type) {
return getConstituentAsBundleRevision(subsystem, symbolicName, version, type).getBundle();
}
@@ -610,6 +688,19 @@ public abstract class SubsystemTest exte
return (BundleRevision)resource;
}
+ protected Subsystem getConstituentAsSubsystem(Subsystem subsystem, String symbolicName, Version version, String type) {
+ Resource resource = getConstituent(subsystem, symbolicName, version, type);
+ return (Subsystem)resource;
+ }
+
+ protected Region getRegion(Subsystem subsystem) {
+ RegionDigraph digraph = getOsgiService(RegionDigraph.class);
+ String name = subsystem.getSymbolicName() + ';' + subsystem.getVersion() + ';' + subsystem.getType() + ';' + subsystem.getSubsystemId();
+ Region region = digraph.getRegion(name);
+ assertNotNull("Region not found: " + name, region);
+ return region;
+ }
+
protected Bundle getRegionContextBundle(Subsystem subsystem) {
BundleContext bc = subsystem.getBundleContext();
assertNotNull("No region context bundle", bc);
@@ -632,6 +723,10 @@ public abstract class SubsystemTest exte
return getSystemBundle().adapt(FrameworkStartLevel.class);
}
+ protected FrameworkWiring getSystemBundleAsFrameworkWiring() {
+ return getSystemBundle().adapt(FrameworkWiring.class);
+ }
+
protected Bundle getSubsystemCoreBundle() {
return findBundleBySymbolicName("org.apache.aries.subsystem.core");
}