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 2011/09/24 00:12:05 UTC

svn commit: r1175049 - in /aries/trunk/subsystem: subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ subsystem-itests/ subsystem-itests/src/test/bundles/tb1/META-...

Author: jwross
Date: Fri Sep 23 22:12:04 2011
New Revision: 1175049

URL: http://svn.apache.org/viewvc?rev=1175049&view=rev
Log:
ARIES-752: Add test for shared feature resources and reference counting.

Adds a new test for shared feature resources and reference counting.
Includes fixes to the implementation in order for the test to pass.
Also includes necessary updates to other tests due to modifications to the shared test features.

Added:
    aries/trunk/subsystem/subsystem-itests/src/test/bundles/tb3/
    aries/trunk/subsystem/subsystem-itests/src/test/bundles/tb3/META-INF/
    aries/trunk/subsystem/subsystem-itests/src/test/bundles/tb3/META-INF/MANIFEST.MF
    aries/trunk/subsystem/subsystem-itests/src/test/bundles/tb3/org/
    aries/trunk/subsystem/subsystem-itests/src/test/bundles/tb3/org/apache/
    aries/trunk/subsystem/subsystem-itests/src/test/bundles/tb3/org/apache/aries/
    aries/trunk/subsystem/subsystem-itests/src/test/bundles/tb3/org/apache/aries/subsystem/
    aries/trunk/subsystem/subsystem-itests/src/test/bundles/tb3/org/apache/aries/subsystem/itests/
    aries/trunk/subsystem/subsystem-itests/src/test/bundles/tb3/org/apache/aries/subsystem/itests/tb3/
    aries/trunk/subsystem/subsystem-itests/src/test/bundles/tb3/org/apache/aries/subsystem/itests/tb3/Empty.java
Modified:
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DeploymentManifest.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Activator.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/AriesSubsystem.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemServiceFactory.java
    aries/trunk/subsystem/subsystem-itests/pom.xml
    aries/trunk/subsystem/subsystem-itests/src/test/bundles/tb1/META-INF/MANIFEST.MF
    aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/FeatureTest.java
    aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/InstallTest.java
    aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/SubsystemTest.java
    aries/trunk/subsystem/subsystem-itests/src/test/resources/feature1/   (props changed)
    aries/trunk/subsystem/subsystem-itests/src/test/resources/feature1/OSGI-INF/SUBSYSTEM.MF
    aries/trunk/subsystem/subsystem-itests/src/test/resources/feature2/   (props changed)
    aries/trunk/subsystem/subsystem-itests/src/test/resources/feature2/OSGI-INF/SUBSYSTEM.MF

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DeploymentManifest.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DeploymentManifest.java?rev=1175049&r1=1175048&r2=1175049&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DeploymentManifest.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DeploymentManifest.java Fri Sep 23 22:12:04 2011
@@ -27,6 +27,7 @@ import org.apache.aries.subsystem.core.i
 import org.apache.aries.subsystem.core.obr.SubsystemEnvironment;
 import org.osgi.framework.resource.Resource;
 import org.osgi.framework.resource.Wire;
+import org.osgi.service.subsystem.SubsystemException;
 
 public class DeploymentManifest extends Manifest {
 	public static DeploymentManifest newInstance(Archive archive, SubsystemEnvironment environment) {
@@ -36,7 +37,12 @@ public class DeploymentManifest extends 
 		Collection<Resource> resources = new ArrayList<Resource>();
 		for (SubsystemContentHeader.Content content : manifest.getSubsystemContent().getContents()) {
 			OsgiIdentityRequirement requirement = new OsgiIdentityRequirement(content.getName(), content.getVersionRange(), content.getType(), false);
-			resources.add(environment.findResource(requirement));
+			Resource resource = environment.findResource(requirement);
+			// If the resource is null, can't continue.
+			// TODO Actually, can continue if resource is optional.
+			if (resource == null)
+				throw new SubsystemException("Resource does not exist: " + resource);
+			resources.add(resource);
 		}
 		// TODO This does not validate that all content bundles were found.
 		Map<Resource, List<Wire>> resolution = Activator.getResolver().resolve(environment, resources, Collections.EMPTY_LIST);

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Activator.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Activator.java?rev=1175049&r1=1175048&r2=1175049&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Activator.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Activator.java Fri Sep 23 22:12:04 2011
@@ -20,12 +20,10 @@ import java.util.Hashtable;
 import java.util.List;
 import java.util.concurrent.Executor;
 
-import org.apache.aries.subsystem.core.obr.SubsystemResolver;
 import org.apache.felix.bundlerepository.RepositoryAdmin;
 import org.eclipse.equinox.region.RegionDigraph;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleListener;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
@@ -131,7 +129,7 @@ public class Activator implements Bundle
 		}
 	}
 	
-	private final BundleListener bundleListener = new SubsystemSynchronousBundleListener();
+//	private final BundleListener bundleListener = new SubsystemSynchronousBundleListener();
 	private final List<ServiceRegistration<?>> registrations = new ArrayList<ServiceRegistration<?>>();
 	
 	public void start(final BundleContext context) throws Exception {
@@ -141,7 +139,7 @@ public class Activator implements Bundle
 		Activator.context = context;
 		register(Subsystem.class.getName(), new SubsystemServiceFactory(), null);
 		register(ResolverHookFactory.class, new SubsystemResolverHookFactory(), null);
-		context.getBundle(0).getBundleContext().addBundleListener(bundleListener);
+//		context.getBundle(0).getBundleContext().addBundleListener(bundleListener);
 		Dictionary<String, Object> properties = new Hashtable<String, Object>();
 		properties.put(EventConstants.EVENT_TOPIC, new String[]{"org/osgi/framework/BundleEvent/*"});
 		register(EventHandler.class, new BundleEventHandler(), properties);
@@ -151,7 +149,7 @@ public class Activator implements Bundle
 		if (LOGGER.isDebugEnabled()) {
 			LOGGER.debug("subsystem activator stopping");
 		}
-		context.getBundle(0).getBundleContext().removeBundleListener(bundleListener);
+//		context.getBundle(0).getBundleContext().removeBundleListener(bundleListener);
 		for (ServiceRegistration<?> r : registrations) {
 			try {
 				r.unregister();

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/AriesSubsystem.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/AriesSubsystem.java?rev=1175049&r1=1175048&r2=1175049&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/AriesSubsystem.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/AriesSubsystem.java Fri Sep 23 22:12:04 2011
@@ -617,17 +617,11 @@ public class AriesSubsystem implements S
 	}
 	
 	private AriesSubsystem getConstituentOf(Resource resource, AriesSubsystem provisionTo, boolean transitive) {
-		// Application and composite resources become constituents of the application or composite.
-		AriesSubsystem constituentOf;
-		if (transitive) {
-			// Transitive dependencies become constituents of the subsystem into which they were provisioned.
-			constituentOf = provisionTo;
-		} 
-		else {
-			// All other resources become constituents of the subsystem in which they were declared.
-			constituentOf = this;
-		}
-		return constituentOf;
+		// Transitive resources always become constituents of the subsystem to which they were provisioned.
+		if (transitive)
+			return provisionTo;
+		// Non-transitive resources become constituents of the subsystem in which they were declared.
+		return this;
 	}
 	
 	private AriesSubsystem getProvisionTo(Resource resource, boolean transitive) {
@@ -648,7 +642,27 @@ public class AriesSubsystem implements S
 		return provisionTo;
 	}
 	
-	private synchronized void initialize(InputStream content) throws BundleException, IOException, URISyntaxException {
+	/*private*/ synchronized void initialize(InputStream content) throws BundleException, IOException, URISyntaxException {
+		// TODO Begin proof of concept.
+		// This is a proof of concept for initializing the relationships between the root subsystem and bundles
+		// that already existed in its region. Not sure this will be the final resting place. Plus, there are issues
+		// since this does not take into account the possibility of already existing bundles going away or new bundles
+		// being installed out of band while this initialization is taking place. Need a bundle event hook for that.
+		if (isRoot()) {
+			for (long id : region.getBundleIds()) {
+				BundleRevision br = Activator.getBundleContext().getBundle(id).adapt(BundleRevision.class);
+				synchronized (resourceToSubsystems) {
+					Set<Subsystem> s = resourceToSubsystems.get(br);
+					if (s == null) {
+						s = new HashSet<Subsystem>();
+						resourceToSubsystems.put(br, s);
+					}
+					s.add(this);
+				}
+			}
+			return;
+		}
+		// TODO End proof of concept.
 		if (content == null)
 			content = new URL(location).openStream();
 		File rootDirectory = Activator.getBundleContext().getDataFile("");
@@ -710,44 +724,42 @@ public class AriesSubsystem implements S
 	}
 	
 	private void installBundleResource(Resource resource, Coordination coordination, boolean transitive) throws BundleException, IOException {
-		AriesSubsystem provisionTo;
-		Bundle bundle;
+		AriesSubsystem provisionTo = null;
+		final BundleRevision revision;
 		synchronized (resourceToSubsystems) {
+			provisionTo = getProvisionTo(resource, transitive);
 			if (resource instanceof BundleRevision) {
 				// This means the resource is a bundle that's already been installed, but we still need to establish the resource->subsystem relationship.
-				// TODO The null check is necessary for when the bundle is in the root subsystem. Currently, the root subsystem is not initialized with
-				// these relationships. Need to decide if that would be better.
-				Set<Subsystem> subsystems = resourceToSubsystems.get(resource);
-				if (subsystems == null) {
-					subsystems = new HashSet<Subsystem>();
-					resourceToSubsystems.put(resource, subsystems);
-				}
-				subsystems.add(this);
-				return;
+				revision = (BundleRevision)resource;
+			}
+			else {
+				URL content = environment.getContent(resource);
+				String location = provisionTo.getSubsystemId() + '@' + provisionTo.getSymbolicName() + '@' + content;
+				Bundle bundle = provisionTo.region.installBundle(location, content.openStream());
+				revision = bundle.adapt(BundleRevision.class);
+			}
+			// TODO The null check is necessary for when the bundle is in the root subsystem. Currently, the root subsystem is not initialized with
+			// these relationships. Need to decide if that would be better.
+			Set<Subsystem> subsystems = resourceToSubsystems.get(revision);
+			if (subsystems == null) {
+				subsystems = new HashSet<Subsystem>();
+				resourceToSubsystems.put(revision, subsystems);
 			}
-			provisionTo = getProvisionTo(resource, transitive);
-			URL content = environment.getContent(resource);
-			String location = provisionTo.getSubsystemId() + '@' + provisionTo.getSymbolicName() + '@' + content;
-			bundle = provisionTo.region.installBundle(location, content.openStream());
-			final BundleRevision revision = bundle.adapt(BundleRevision.class);
-			Set<Subsystem> subsystems = new HashSet<Subsystem>();
 			subsystems.add(this);
-			resourceToSubsystems.put(revision, subsystems);
 		}
 		final AriesSubsystem constituentOf = getConstituentOf(resource, provisionTo, transitive);
-		final BundleRevision revision = bundle.adapt(BundleRevision.class);
 		coordination.addParticipant(new Participant() {
 			public void ended(Coordination coordination) throws Exception {
 				constituentOf.constituents.add(revision);
 			}
 	
 			public void failed(Coordination coordination) throws Exception {
-				revision.getBundle().uninstall();
 				synchronized (resourceToSubsystems) {
 					Set<Subsystem> subsystems = resourceToSubsystems.get(revision);
 					subsystems.remove(AriesSubsystem.this);
 					if (subsystems.isEmpty()) {
 						resourceToSubsystems.remove(revision);
+						revision.getBundle().uninstall();
 					}
 				}
 			}
@@ -899,7 +911,7 @@ public class AriesSubsystem implements S
 			if (!subsystems.isEmpty()) {
 				return;
 			}
-			subsystems.remove(resource);
+			resourceToSubsystems.remove(resource);
 		}
 		((BundleRevision)resource).getBundle().uninstall();
 	}

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemServiceFactory.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemServiceFactory.java?rev=1175049&r1=1175048&r2=1175049&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemServiceFactory.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemServiceFactory.java Fri Sep 23 22:12:04 2011
@@ -30,6 +30,7 @@ public class SubsystemServiceFactory imp
 	
 	public SubsystemServiceFactory() throws Exception {
 		rootSubsystem = new AriesSubsystem();
+		rootSubsystem.initialize(null);
 		Region region = Activator.getRegionDigraph().getRegion(Activator.getBundleContext().getBundle());
 		regionsToSubsystems.put(region, rootSubsystem);
 	}

Modified: aries/trunk/subsystem/subsystem-itests/pom.xml
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/pom.xml?rev=1175049&r1=1175048&r2=1175049&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-itests/pom.xml (original)
+++ aries/trunk/subsystem/subsystem-itests/pom.xml Fri Sep 23 22:12:04 2011
@@ -352,12 +352,49 @@
 							<classesDirectory>${project.build.directory}/test-classes</classesDirectory>
 							<includes>
 								<include>org/apache/aries/subsystem/itests/tb2/**</include>
+								<include>org/apache/aries/subsystem/itests/tb3/**</include>
 							</includes>
 							<outputDirectory>src/test/resources/feature2</outputDirectory>
 							<finalName>tb2</finalName>
 						</configuration>
 						<phase>process-test-classes</phase>
 					</execution>
+					<execution>
+						<id>tb3-feature1</id>
+						<goals>
+							<goal>jar</goal>
+						</goals>
+						<configuration>
+							<archive>
+								<manifestFile>src/test/bundles/tb3/META-INF/MANIFEST.MF</manifestFile>
+							</archive>
+							<classesDirectory>${project.build.directory}/test-classes</classesDirectory>
+							<includes>
+								<include>org/apache/aries/subsystem/itests/tb3/**</include>
+							</includes>
+							<outputDirectory>src/test/resources/feature1</outputDirectory>
+							<finalName>tb3</finalName>
+						</configuration>
+						<phase>process-test-classes</phase>
+					</execution>
+					<execution>
+						<id>tb3-feature2</id>
+						<goals>
+							<goal>jar</goal>
+						</goals>
+						<configuration>
+							<archive>
+								<manifestFile>src/test/bundles/tb3/META-INF/MANIFEST.MF</manifestFile>
+							</archive>
+							<classesDirectory>${project.build.directory}/test-classes</classesDirectory>
+							<includes>
+								<include>org/apache/aries/subsystem/itests/tb3/**</include>
+							</includes>
+							<outputDirectory>src/test/resources/feature2</outputDirectory>
+							<finalName>tb3</finalName>
+						</configuration>
+						<phase>process-test-classes</phase>
+					</execution>
 				</executions>
 			</plugin>
 			<plugin>
@@ -389,6 +426,18 @@
 							</sources>
 						</configuration>
 					</execution>
+					<execution>
+						<id>add-source-tb3</id>
+						<phase>generate-sources</phase>
+						<goals>
+							<goal>add-test-source</goal>
+						</goals>
+						<configuration>
+							<sources>
+								<source>src/test/bundles/tb3</source>
+							</sources>
+						</configuration>
+					</execution>
 				</executions>
 			</plugin>
             <plugin>

Modified: aries/trunk/subsystem/subsystem-itests/src/test/bundles/tb1/META-INF/MANIFEST.MF
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/src/test/bundles/tb1/META-INF/MANIFEST.MF?rev=1175049&r1=1175048&r2=1175049&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-itests/src/test/bundles/tb1/META-INF/MANIFEST.MF (original)
+++ aries/trunk/subsystem/subsystem-itests/src/test/bundles/tb1/META-INF/MANIFEST.MF Fri Sep 23 22:12:04 2011
@@ -5,3 +5,4 @@ Bundle-SymbolicName: org.apache.aries.su
 Bundle-Version: 1.0.0
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
 Export-Package: org.apache.aries.subsystem.itests.tb1
+Import-Package: org.apache.aries.subsystem.itests.tb3

Added: aries/trunk/subsystem/subsystem-itests/src/test/bundles/tb3/META-INF/MANIFEST.MF
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/src/test/bundles/tb3/META-INF/MANIFEST.MF?rev=1175049&view=auto
==============================================================================
--- aries/trunk/subsystem/subsystem-itests/src/test/bundles/tb3/META-INF/MANIFEST.MF (added)
+++ aries/trunk/subsystem/subsystem-itests/src/test/bundles/tb3/META-INF/MANIFEST.MF Fri Sep 23 22:12:04 2011
@@ -0,0 +1,7 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: TB3
+Bundle-SymbolicName: org.apache.aries.subsystem.itests.tb3
+Bundle-Version: 1.0.0
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Export-Package: org.apache.aries.subsystem.itests.tb3

Added: aries/trunk/subsystem/subsystem-itests/src/test/bundles/tb3/org/apache/aries/subsystem/itests/tb3/Empty.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/src/test/bundles/tb3/org/apache/aries/subsystem/itests/tb3/Empty.java?rev=1175049&view=auto
==============================================================================
--- aries/trunk/subsystem/subsystem-itests/src/test/bundles/tb3/org/apache/aries/subsystem/itests/tb3/Empty.java (added)
+++ aries/trunk/subsystem/subsystem-itests/src/test/bundles/tb3/org/apache/aries/subsystem/itests/tb3/Empty.java Fri Sep 23 22:12:04 2011
@@ -0,0 +1,5 @@
+package org.apache.aries.subsystem.itests.tb3;
+
+public class Empty {
+
+}

Modified: aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/FeatureTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/FeatureTest.java?rev=1175049&r1=1175048&r2=1175049&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/FeatureTest.java (original)
+++ aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/FeatureTest.java Fri Sep 23 22:12:04 2011
@@ -29,6 +29,8 @@ import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.osgi.framework.Version;
+import org.osgi.framework.resource.ResourceConstants;
 import org.osgi.service.subsystem.Subsystem;
 import org.osgi.service.subsystem.SubsystemConstants;
 
@@ -64,35 +66,38 @@ public class FeatureTest extends Subsyst
 		if (createdApplications) {
 			return;
 		}
-		createApplication("feature2", new String[]{"tb2.jar"});
-		createApplication("feature1", new String[]{"tb1.jar", "feature2.ssa"});
+		createApplication("feature2", new String[]{"tb2.jar", "tb3.jar"});
+		createApplication("feature1", new String[]{"tb1.jar", "feature2.ssa", "tb3.jar"});
 		createdApplications = true;
 	}
 
 	@Test
 	public void testFeature1() throws Exception {
-		Subsystem subsystem = installSubsystemFromFile("feature1.ssa");
+		Subsystem feature1 = installSubsystemFromFile("feature1.ssa");
+		Subsystem feature2 = null;
 		AssertionError error = null;
 		try {
-			assertSymbolicName("org.apache.aries.subsystem.feature1", subsystem);
-			assertVersion("1.0.0", subsystem);
-			assertConstituents(4, subsystem);
-			assertChildren(1, subsystem);
-			assertEvent(subsystem.getChildren().iterator().next(), Subsystem.State.INSTALLING, SubsystemConstants.EVENT_TYPE.INSTALLING, 5000);
-			assertEvent(subsystem.getChildren().iterator().next(), Subsystem.State.INSTALLED, SubsystemConstants.EVENT_TYPE.INSTALLED, 5000);
-			assertSymbolicName("org.apache.aries.subsystem.feature2", subsystem.getChildren().iterator().next());
-			assertVersion("1.0.0", subsystem.getChildren().iterator().next());
-			assertConstituents(1, subsystem.getChildren().iterator().next());
+			assertSymbolicName("org.apache.aries.subsystem.feature1", feature1);
+			assertVersion("1.0.0", feature1);
+			assertConstituents(5, feature1);
+			assertChildren(1, feature1);
+			feature2 = feature1.getChildren().iterator().next();
+			assertEvent(feature2, Subsystem.State.INSTALLING, SubsystemConstants.EVENT_TYPE.INSTALLING, 5000);
+			assertEvent(feature2, Subsystem.State.INSTALLED, SubsystemConstants.EVENT_TYPE.INSTALLED, 5000);
+			assertSymbolicName("org.apache.aries.subsystem.feature2", feature2);
+			assertVersion("1.0.0", feature2);
+			assertConstituents(2, feature2);
+			assertChildren(0, feature2);
 			// TODO Test internal events for installation.
-			startSubsystem(subsystem);
-			assertEvent(subsystem.getChildren().iterator().next(), Subsystem.State.RESOLVING, SubsystemConstants.EVENT_TYPE.RESOLVING, 5000);
-			assertEvent(subsystem.getChildren().iterator().next(), Subsystem.State.RESOLVED, SubsystemConstants.EVENT_TYPE.RESOLVED, 5000);
-			assertEvent(subsystem.getChildren().iterator().next(), Subsystem.State.STARTING, SubsystemConstants.EVENT_TYPE.STARTING, 5000);
-			assertEvent(subsystem.getChildren().iterator().next(), Subsystem.State.ACTIVE, SubsystemConstants.EVENT_TYPE.STARTED, 5000);
+			startSubsystem(feature1);
+			assertEvent(feature2, Subsystem.State.RESOLVING, SubsystemConstants.EVENT_TYPE.RESOLVING, 5000);
+			assertEvent(feature2, Subsystem.State.RESOLVED, SubsystemConstants.EVENT_TYPE.RESOLVED, 5000);
+			assertEvent(feature2, Subsystem.State.STARTING, SubsystemConstants.EVENT_TYPE.STARTING, 5000);
+			assertEvent(feature2, Subsystem.State.ACTIVE, SubsystemConstants.EVENT_TYPE.STARTED, 5000);
 			// TODO Test internal events for starting.
-			stopSubsystem(subsystem);
-			assertEvent(subsystem.getChildren().iterator().next(), Subsystem.State.STOPPING, SubsystemConstants.EVENT_TYPE.STOPPING, 5000);
-			assertEvent(subsystem.getChildren().iterator().next(), Subsystem.State.RESOLVED, SubsystemConstants.EVENT_TYPE.STOPPED, 5000);
+			stopSubsystem(feature1);
+			assertEvent(feature2, Subsystem.State.STOPPING, SubsystemConstants.EVENT_TYPE.STOPPING, 5000);
+			assertEvent(feature2, Subsystem.State.RESOLVED, SubsystemConstants.EVENT_TYPE.STOPPED, 5000);
 			// TODO Test internal events for stopping.
 		}
 		catch (AssertionError e) {
@@ -101,12 +106,44 @@ public class FeatureTest extends Subsyst
 		}
 		finally {
 			try {
-				Subsystem child = subsystem.getChildren().iterator().next();
-				uninstallSubsystem(subsystem);
-				assertEvent(child, Subsystem.State.UNINSTALLING, SubsystemConstants.EVENT_TYPE.UNINSTALLING, 5000);
-				assertEvent(child, Subsystem.State.UNINSTALLED, SubsystemConstants.EVENT_TYPE.UNINSTALLED, 5000);
-				// TODO Test internal events for uninstalling.
-				assertNotChild(subsystem, child);
+				uninstallSubsystem(feature1);
+				if (feature2 != null) {
+					assertEvent(feature2, Subsystem.State.UNINSTALLING, SubsystemConstants.EVENT_TYPE.UNINSTALLING, 5000);
+					assertEvent(feature2, Subsystem.State.UNINSTALLED, SubsystemConstants.EVENT_TYPE.UNINSTALLED, 5000);
+					// TODO Test internal events for uninstalling.
+					assertNotChild(feature1, feature2);
+				}
+			}
+			catch (AssertionError e) {
+				if (error == null)
+					throw e;
+				e.printStackTrace();
+			}
+		}
+	}
+	
+	@Test
+	public void testSharedFeatureResource() throws Exception {
+		Subsystem feature1 = installSubsystemFromFile("feature1.ssa");
+		AssertionError error = null;
+		try {
+			assertConstituent(feature1, "org.apache.aries.subsystem.itests.tb3", Version.parseVersion("1.0.0"), ResourceConstants.IDENTITY_TYPE_BUNDLE);
+			Subsystem feature2 = feature1.getChildren().iterator().next();
+			// TODO This needs to be better implemented and put into a utility method on the superclass.
+			while (!feature2.getState().equals(Subsystem.State.INSTALLED))
+				Thread.sleep(100);
+			assertConstituent(feature2, "org.apache.aries.subsystem.itests.tb3", Version.parseVersion("1.0.0"), ResourceConstants.IDENTITY_TYPE_BUNDLE);
+			uninstallSubsystem(feature2);
+			assertNotChild(feature1, feature2);
+			assertConstituent(feature1, "org.apache.aries.subsystem.itests.tb3", Version.parseVersion("1.0.0"), ResourceConstants.IDENTITY_TYPE_BUNDLE);
+		}
+		catch (AssertionError e) {
+			error = e;
+			throw e;
+		}
+		finally {
+			try {
+				uninstallSubsystem(feature1);
 			}
 			catch (AssertionError e) {
 				if (error == null)

Modified: aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/InstallTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/InstallTest.java?rev=1175049&r1=1175048&r2=1175049&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/InstallTest.java (original)
+++ aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/InstallTest.java Fri Sep 23 22:12:04 2011
@@ -65,15 +65,24 @@ public class InstallTest extends Subsyst
 		if (createdApplications) {
 			return;
 		}
-		createApplication("feature2", new String[]{"tb2.jar"});
-		createApplication("feature1", new String[]{"tb1.jar", "feature2.ssa"});
+		createApplication("feature2", new String[]{"tb2.jar", "tb3.jar"});
+		createApplication("feature1", new String[]{"tb1.jar", "feature2.ssa", "tb3.jar"});
 		createdApplications = true;
 	}
 
 	@Test
 	public void testReturnExistingSubsystemWithSameLocation() throws Exception {
 		Subsystem subsystem1 = installSubsystemFromFile("feature1.ssa");
-		Subsystem subsystem2 = subsystem1.install(subsystem1.getLocation());
-		assertSame(subsystem1, subsystem2);
+		try {
+			// Need to wait for the nested feature within feature1 to install. Perhaps use a simpler subsystem for this test?
+			// TODO This needs to be better implemented and put into a utility method on the superclass.
+			while (!subsystem1.getChildren().iterator().next().getState().equals(Subsystem.State.INSTALLED))
+				Thread.sleep(100);
+			Subsystem subsystem2 = subsystem1.install(subsystem1.getLocation());
+			assertSame(subsystem1, subsystem2);
+		}
+		finally {
+			uninstallSubsystem(subsystem1);
+		}
 	}
 }

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=1175049&r1=1175048&r2=1175049&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 Fri Sep 23 22:12:04 2011
@@ -34,6 +34,9 @@ import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
 
+import junit.framework.Assert;
+
+import org.apache.aries.subsystem.core.ResourceHelper;
 import org.apache.aries.subsystem.core.obr.felix.RepositoryAdminRepository;
 import org.apache.aries.subsystem.itests.util.RepositoryGenerator;
 import org.apache.aries.subsystem.itests.util.Utils;
@@ -43,6 +46,7 @@ import org.ops4j.pax.exam.container.def.
 import org.osgi.framework.Bundle;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.framework.Version;
+import org.osgi.framework.resource.Resource;
 import org.osgi.service.event.Event;
 import org.osgi.service.event.EventConstants;
 import org.osgi.service.event.EventHandler;
@@ -50,10 +54,10 @@ import org.osgi.service.repository.Repos
 import org.osgi.service.subsystem.Subsystem;
 import org.osgi.service.subsystem.Subsystem.State;
 import org.osgi.service.subsystem.SubsystemConstants;
-import org.osgi.service.subsystem.SubsystemConstants.EVENT_TYPE;;
+import org.osgi.service.subsystem.SubsystemConstants.EVENT_TYPE;
 
 public abstract class SubsystemTest extends IntegrationTest {
-	protected static class SubsystemTestEventHandler implements EventHandler {
+	protected static class SubsystemEventHandler implements EventHandler {
 		private final Map<Long, List<Event>> subsystemIdToEvents = new HashMap<Long, List<Event>>();
 		
 		public void clear() {
@@ -143,8 +147,8 @@ public abstract class SubsystemTest exte
 		return options;
 	}
 	
-	protected final SubsystemTestEventHandler subsystemEvents = new SubsystemTestEventHandler();
-	protected final SubsystemTestEventHandler subsystemInternalEvents = new SubsystemTestEventHandler();
+	protected final SubsystemEventHandler subsystemEvents = new SubsystemEventHandler();
+	protected final SubsystemEventHandler subsystemInternalEvents = new SubsystemEventHandler();
 	
 	protected Subsystem rootSubsystem;
 	
@@ -186,6 +190,19 @@ public abstract class SubsystemTest exte
 		assertTrue("Parent did not contain all children", parent.getChildren().containsAll(children));
 	}
 	
+	protected void assertConstituent(Subsystem subsystem, String symbolicName, Version version, String type) {
+		for (Resource resource : subsystem.getConstituents()) {
+			if (symbolicName.equals(ResourceHelper.getSymbolicNameAttribute(resource))) {
+				if (version != null)
+					assertVersion(version, ResourceHelper.getVersionAttribute(resource));
+				if (type != null)
+					assertEquals("Wrong type", type, ResourceHelper.getTypeAttribute(resource));
+				return;
+			}
+		}
+		Assert.fail("Constituent not found: " + symbolicName);
+	}
+	
 	protected void assertConstituents(int size, Subsystem subsystem) {
 		assertEquals("Wrong number of constituents", size, subsystem.getConstituents().size());
 	}
@@ -320,7 +337,11 @@ public abstract class SubsystemTest exte
 	}
 	
 	protected void assertVersion(Version expected, Subsystem subsystem) {
-		assertEquals("Wrong version: " + subsystem.getVersion(), expected, subsystem.getVersion());
+		assertVersion(expected, subsystem.getVersion());
+	}
+	
+	protected void assertVersion(Version expected, Version actual) {
+		assertEquals("Wrong version", expected, actual);
 	}
 	
 	protected Bundle getSubsystemCoreBundle() {

Propchange: aries/trunk/subsystem/subsystem-itests/src/test/resources/feature1/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Fri Sep 23 22:12:04 2011
@@ -1 +1,2 @@
 tb1.jar
+tb3.jar

Modified: aries/trunk/subsystem/subsystem-itests/src/test/resources/feature1/OSGI-INF/SUBSYSTEM.MF
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/src/test/resources/feature1/OSGI-INF/SUBSYSTEM.MF?rev=1175049&r1=1175048&r2=1175049&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-itests/src/test/resources/feature1/OSGI-INF/SUBSYSTEM.MF (original)
+++ aries/trunk/subsystem/subsystem-itests/src/test/resources/feature1/OSGI-INF/SUBSYSTEM.MF Fri Sep 23 22:12:04 2011
@@ -7,5 +7,6 @@ Subsystem-Description: %feature1.descrip
 Subsystem-Content: org.apache.aries.subsystem.itests.tb1,
  derby;version=10.5.0,
  org.apache.felix.fileinstall;version="[2.0,3.0)",
- org.apache.aries.subsystem.feature2;version=1.0.0;type=osgi.subsystem;start-order:=2
+ org.apache.aries.subsystem.feature2;version=1.0.0;type=osgi.subsystem;start-order:=2,
+ org.apache.aries.subsystem.itests.tb3
 Subsystem-Type: osgi.feature

Propchange: aries/trunk/subsystem/subsystem-itests/src/test/resources/feature2/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Fri Sep 23 22:12:04 2011
@@ -1 +1,2 @@
 tb2.jar
+tb3.jar

Modified: aries/trunk/subsystem/subsystem-itests/src/test/resources/feature2/OSGI-INF/SUBSYSTEM.MF
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/src/test/resources/feature2/OSGI-INF/SUBSYSTEM.MF?rev=1175049&r1=1175048&r2=1175049&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-itests/src/test/resources/feature2/OSGI-INF/SUBSYSTEM.MF (original)
+++ aries/trunk/subsystem/subsystem-itests/src/test/resources/feature2/OSGI-INF/SUBSYSTEM.MF Fri Sep 23 22:12:04 2011
@@ -1,4 +1,5 @@
 Subsystem-SymbolicName: org.apache.aries.subsystem.feature2
 Subsystem-Version: 1.0.0
 Subsystem-Type: osgi.feature
-Subsystem-Content: org.apache.aries.subsystem.itests.tb2;version=2.0.0
+Subsystem-Content: org.apache.aries.subsystem.itests.tb2;version=2.0.0,
+ org.apache.aries.subsystem.itests.tb3