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/03/06 01:02:58 UTC

svn commit: r1297302 - 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-core/src/main/java/org/apache/aries/subsystem/core/...

Author: jwross
Date: Tue Mar  6 00:02:57 2012
New Revision: 1297302

URL: http://svn.apache.org/viewvc?rev=1297302&view=rev
Log:
ARIES-825: Update subsystems to latest Subsystem, Resolver, and Repository APIs.

Initial support for Require-Capability header in applications.

Added:
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Constants.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/archive/RequireCapabilityHeader.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/RegionContextBundleHelper.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResolverHook.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemSynchronousBundleListener.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/BundleResource.java
    aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/ApplicationTest.java
    aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/CompositeTest.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/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=1297302&r1=1297301&r2=1297302&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 Tue Mar  6 00:02:57 2012
@@ -116,6 +116,9 @@ public class DeploymentManifest {
 					Header<?> header = computeImportPackageHeader(resolution, deployedContent, acceptDependencies);
 					if (header != null)
 						headers.put(IMPORT_PACKAGE, header);
+					header = computeRequireCapabilityHeader(resolution, deployedContent, acceptDependencies);
+					if (header != null)
+						headers.put(REQUIRE_CAPABILITY, header);
 				}
 				// TODO Compute additional headers for an application.
 			}
@@ -234,4 +237,33 @@ public class DeploymentManifest {
 			return null;
 		return new ImportPackageHeader(clauses);
 	}
+	
+	private static RequireCapabilityHeader computeRequireCapabilityHeader(
+			Map<Resource, List<Wire>> resolution, 
+			Collection<Resource> content,
+			boolean acceptDependencies) {
+		Collection<RequireCapabilityHeader.Clause> clauses = new ArrayList<RequireCapabilityHeader.Clause>();
+		for (Entry<Resource, List<Wire>> entry : resolution.entrySet()) {
+			for (Wire wire : entry.getValue()) {
+				Resource provider = wire.getProvider();
+				if (content.contains(provider))
+					// If the provider is a content resource, we don't need an imported capability.
+					continue;
+				// The provider is a dependency that is already provisioned or needs provisioning.
+				if (acceptDependencies && !((provider instanceof BundleRevision) || (provider instanceof AriesSubsystem)))
+					// If the application accepts dependencies and the provider is a dependency that needs provisioning,
+					// we don't need an import.
+					continue;
+				// For all other cases, we need an import.
+				Requirement requirement = wire.getRequirement();
+				// TODO Not sure if the startsWith check will be sufficient.
+				if (!requirement.getNamespace().startsWith("osgi.")) {
+					clauses.add(new RequireCapabilityHeader.Clause(requirement));
+				}
+			}
+		}
+		if (clauses.isEmpty())
+			return null;
+		return new RequireCapabilityHeader(clauses);
+	}
 }

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/RequireCapabilityHeader.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/RequireCapabilityHeader.java?rev=1297302&r1=1297301&r2=1297302&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/RequireCapabilityHeader.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/RequireCapabilityHeader.java Tue Mar  6 00:02:57 2012
@@ -6,11 +6,13 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import org.osgi.framework.Constants;
+import org.osgi.resource.Requirement;
 
 public class RequireCapabilityHeader implements Header<RequireCapabilityHeader.Clause> {
 	public static class Clause implements org.apache.aries.subsystem.core.archive.Clause {
@@ -46,6 +48,12 @@ public class RequireCapabilityHeader imp
 			fillInDefaults(parameters);
 		}
 		
+		public Clause(Requirement requirement) {
+			namespace = requirement.getNamespace();
+			for (Entry<String, String> directive : requirement.getDirectives().entrySet())
+				parameters.put(directive.getKey(), DirectiveFactory.createDirective(directive.getKey(), directive.getValue()));
+		}
+		
 		@Override
 		public Attribute getAttribute(String name) {
 			Parameter result = parameters.get(name);
@@ -122,14 +130,24 @@ public class RequireCapabilityHeader imp
 	
 	private static final Pattern PATTERN = Pattern.compile('(' + Grammar.REQUIREMENT + ")(?=,|\\z)");
 	
-	private final Set<Clause> clauses = new HashSet<Clause>();
-	
-	public RequireCapabilityHeader(String value) {
-		Matcher matcher = PATTERN.matcher(value);
+	private static Collection<Clause> processHeader(String header) {
+		Matcher matcher = PATTERN.matcher(header);
+		Set<Clause> clauses = new HashSet<Clause>();
 		while (matcher.find())
 			clauses.add(new Clause(matcher.group()));
+		return clauses;
+	}
+	
+	private final Set<Clause> clauses;
+	
+	public RequireCapabilityHeader(String value) {
+		this(processHeader(value));
+	}
+	
+	public RequireCapabilityHeader(Collection<Clause> clauses) {
 		if (clauses.isEmpty())
 			throw new IllegalArgumentException("A " + NAME + " header must have at least one clause");
+		this.clauses = new HashSet<Clause>(clauses);
 	}
 
 	@Override

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=1297302&r1=1297301&r2=1297302&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 Tue Mar  6 00:02:57 2012
@@ -97,7 +97,7 @@ public class Activator implements Bundle
 		registrations.add(bundleContext.registerService(ResolverHookFactory.class, new SubsystemResolverHookFactory(), null));
 		// TODO The registration of the Resolver service should be temporary, unless Felix 
 		// does not have an official release at the time.
-		registrations.add(bundleContext.registerService(Resolver.class, new ResolverImpl(null), null));
+//		registrations.add(bundleContext.registerService(Resolver.class, new ResolverImpl(null), null));
 		registrar = new SubsystemServiceRegistrar(bundleContext);
 		root = new AriesSubsystem();
 		root.install();

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=1297302&r1=1297301&r2=1297302&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 Tue Mar  6 00:02:57 2012
@@ -120,6 +120,24 @@ public class AriesSubsystem implements S
 		return result;
 	}
 	
+	private static synchronized void addResourceToSubsystem(Resource resource, AriesSubsystem subsystem) {
+		Set<AriesSubsystem> subsystems = resourceToSubsystems.get(resource);
+		if (subsystems == null) {
+			subsystems = new HashSet<AriesSubsystem>();
+			resourceToSubsystems.put(resource, subsystems);
+		}
+		subsystems.add(subsystem);
+	}
+	
+	private static synchronized void removeResourceToSubsystem(Resource resource, AriesSubsystem subsystem) {
+		Set<AriesSubsystem> subsystems = resourceToSubsystems.get(resource);
+		if (subsystems == null)
+			return;
+		subsystems.remove(subsystem);
+		if (subsystems.isEmpty())
+			resourceToSubsystems.remove(resource);
+	}
+	
 	private static void copyContent(InputStream content, File destination) throws IOException {
 		copyContent(
 				new BufferedInputStream(content),
@@ -617,24 +635,15 @@ public class AriesSubsystem implements S
 	}
 	
 	void bundleChanged(BundleEvent event) {
+		Resource resource = event.getBundle().adapt(BundleRevision.class);
 		switch (event.getType()) {
-			case BundleEvent.STARTING:
-				if (State.STARTING.equals(getState())) {
-					return;
-				}
-				start();
-				break;
-			case BundleEvent.STOPPING:
-				if (State.STOPPING.equals(getState())) {
-					return;
-				}
-				stop();
+			case BundleEvent.INSTALLED:
+				addResourceToSubsystem(resource, this);
+				constituents.add(resource);
 				break;
 			case BundleEvent.UNINSTALLED:
-				if (EnumSet.of(State.UNINSTALLING, State.UNINSTALLED).contains(getState())) {
-					return;
-				}
-				uninstall();
+				constituents.remove(resource);
+				removeResourceToSubsystem(resource, this);
 				break;
 		}
 	}

Added: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Constants.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Constants.java?rev=1297302&view=auto
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Constants.java (added)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Constants.java Tue Mar  6 00:02:57 2012
@@ -0,0 +1,9 @@
+package org.apache.aries.subsystem.core.internal;
+
+public class Constants {
+	public static final String BundleSymbolicName = org.osgi.framework.Constants.BUNDLE_SYMBOLICNAME;
+	public static final String BundleVersion = org.osgi.framework.Constants.BUNDLE_VERSION;
+	public static final String RegionContextBundleSymbolicNamePrefix = "org.osgi.service.subsystem.region.context.";
+	
+	private Constants() {}
+}

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/RegionContextBundleHelper.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/RegionContextBundleHelper.java?rev=1297302&r1=1297301&r2=1297302&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/RegionContextBundleHelper.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/RegionContextBundleHelper.java Tue Mar  6 00:02:57 2012
@@ -10,12 +10,11 @@ import java.util.jar.Manifest;
 
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleException;
-import org.osgi.framework.Constants;
 import org.osgi.framework.Version;
 import org.osgi.framework.wiring.BundleRevision;
 
 public class RegionContextBundleHelper {
-	public static final String SYMBOLICNAME_PREFIX = "org.osgi.service.subsystem.region.context.";
+	public static final String SYMBOLICNAME_PREFIX = Constants.RegionContextBundleSymbolicNamePrefix;
 	public static final Version VERSION = Version.parseVersion("1.0.0");
 	
 	public static BundleRevision installRegionContextBundle(AriesSubsystem subsystem) throws BundleException, IOException {
@@ -47,8 +46,8 @@ public class RegionContextBundleHelper {
 	private static Manifest createManifest(String symbolicName) {
 		Manifest manifest = new Manifest();
 		manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
-		manifest.getMainAttributes().putValue(Constants.BUNDLE_SYMBOLICNAME, symbolicName);
-		manifest.getMainAttributes().putValue(Constants.BUNDLE_VERSION, VERSION.toString());
+		manifest.getMainAttributes().putValue(Constants.BundleSymbolicName, symbolicName);
+		manifest.getMainAttributes().putValue(Constants.BundleVersion, VERSION.toString());
 		return manifest;
 	}
 	

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResolverHook.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResolverHook.java?rev=1297302&r1=1297301&r2=1297302&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResolverHook.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResolverHook.java Tue Mar  6 00:02:57 2012
@@ -38,7 +38,11 @@ public class SubsystemResolverHook imple
 	public void filterResolvable(Collection<BundleRevision> candidates) {
 		try {
 			for (Iterator<BundleRevision> iterator = candidates.iterator(); iterator.hasNext();) {
-				Collection<AriesSubsystem> subsystems = AriesSubsystem.getSubsystems(iterator.next());
+				BundleRevision revision = iterator.next();
+				if (revision.getSymbolicName().startsWith(Constants.RegionContextBundleSymbolicNamePrefix))
+					// Don't want to filter out the region context bundle.
+					continue;
+				Collection<AriesSubsystem> subsystems = AriesSubsystem.getSubsystems(revision);
 				for (AriesSubsystem subsystem : subsystems) {
 					if (subsystem.isFeature()) {
 						// Feature subsystems require no isolation.

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemSynchronousBundleListener.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemSynchronousBundleListener.java?rev=1297302&r1=1297301&r2=1297302&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemSynchronousBundleListener.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemSynchronousBundleListener.java Tue Mar  6 00:02:57 2012
@@ -13,8 +13,12 @@
  */
 package org.apache.aries.subsystem.core.internal;
 
+import java.util.Collection;
+
 import org.osgi.framework.BundleEvent;
 import org.osgi.framework.SynchronousBundleListener;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.resource.Resource;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -22,10 +26,18 @@ public class SubsystemSynchronousBundleL
 	private static final Logger logger = LoggerFactory.getLogger(SubsystemSynchronousBundleListener.class);
 	
 	public void bundleChanged(BundleEvent event) {
-		String type;
+		String type = null;
 		switch (event.getType()) {
 			case BundleEvent.INSTALLED:
 				type = "INSTALLED";
+			case BundleEvent.UNINSTALLED:
+				if (type == null)
+					type = "UNINSTALLED";
+				Resource resource = event.getOrigin().adapt(BundleRevision.class);
+				Collection<AriesSubsystem> subsystems = AriesSubsystem.getSubsystems(resource);
+				for (AriesSubsystem subsystem : subsystems) {
+					subsystem.bundleChanged(event);
+				}
 				break;
 			case BundleEvent.LAZY_ACTIVATION:
 				type = "LAZY_ACTIVATION";
@@ -45,9 +57,6 @@ public class SubsystemSynchronousBundleL
 			case BundleEvent.STOPPING:
 				type = "STOPPING";
 				break;
-			case BundleEvent.UNINSTALLED:
-				type = "UNINSTALLED";
-				break;
 			case BundleEvent.UNRESOLVED:
 				type = "UNRESOLVED";
 				break;

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/BundleResource.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/BundleResource.java?rev=1297302&r1=1297301&r2=1297302&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/BundleResource.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/BundleResource.java Tue Mar  6 00:02:57 2012
@@ -24,6 +24,8 @@ import java.util.jar.Manifest;
 import org.apache.aries.subsystem.core.archive.BundleManifest;
 import org.apache.aries.subsystem.core.archive.ExportPackageHeader;
 import org.apache.aries.subsystem.core.archive.ImportPackageHeader;
+import org.apache.aries.subsystem.core.archive.RequireCapabilityHeader;
+import org.apache.aries.subsystem.core.archive.RequireCapabilityRequirement;
 import org.apache.aries.subsystem.core.internal.OsgiIdentityCapability;
 import org.osgi.resource.Capability;
 import org.osgi.resource.Requirement;
@@ -58,13 +60,15 @@ public class BundleResource implements R
 			catch (IOException e) {}
 		}
 		ExportPackageHeader eph = (ExportPackageHeader)manifest.getHeader(ExportPackageHeader.NAME);
-		if (eph != null) {
+		if (eph != null)
 			capabilities.addAll(eph.toCapabilities(this));
-		}
 		ImportPackageHeader iph = (ImportPackageHeader)manifest.getHeader(ImportPackageHeader.NAME);
-		if (iph != null) {
+		if (iph != null)
 			requirements.addAll(iph.getRequirements(this));
-		}
+		RequireCapabilityHeader rch = (RequireCapabilityHeader)manifest.getHeader(RequireCapabilityHeader.NAME);
+		if (rch != null)
+			for (RequireCapabilityHeader.Clause clause : rch.getClauses())
+				requirements.add(new RequireCapabilityRequirement(clause));
 	}
 	
 	private BundleResource(String content) throws IOException {

Modified: aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/ApplicationTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/ApplicationTest.java?rev=1297302&r1=1297301&r2=1297302&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/ApplicationTest.java (original)
+++ aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/ApplicationTest.java Tue Mar  6 00:02:57 2012
@@ -23,6 +23,8 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.jar.Attributes;
 import java.util.jar.JarOutputStream;
 import java.util.jar.Manifest;
@@ -49,6 +51,58 @@ import org.osgi.service.subsystem.Subsys
 
 @RunWith(JUnit4TestRunner.class)
 public class ApplicationTest extends SubsystemTest {
+	/*
+	 * Subsystem-SymbolicName: application.a.esa
+	 */
+	private static final String APPLICATION_A = "application.a.esa";
+	
+	/*
+	 * Bundle-SymbolicName: bundle.a.jar
+	 * Require-Capability: foo; filter:="(foo=bar)"
+	 */
+	private static final String BUNDLE_A = "bundle.a.jar";
+	/*
+	 * Bundle-SymbolicName: bundle.b.jar
+	 * Provide-Capability: foo; foo=bar
+	 */
+	private static final String BUNDLE_B = "bundle.b.jar";
+	
+	private static boolean createdTestFiles;
+	
+	@Before
+	public static void createTestFiles() throws Exception {
+		if (createdTestFiles)
+			return;
+		createBundleA();
+		createBundleB();
+		createApplicationA();
+		createdTestFiles = true;
+	}
+	
+	private static void createBundleA() throws IOException {
+		Map<String, String> headers = new HashMap<String, String>();
+		headers.put(Constants.REQUIRE_CAPABILITY, "foo; filter:=\"(foo=bar)\"");
+		createBundle(BUNDLE_A, "1.0.0", headers);
+	}
+	
+	private static void createBundleB() throws IOException {
+		Map<String, String> headers = new HashMap<String, String>();
+		headers.put(Constants.PROVIDE_CAPABILITY, "foo; foo=bar");
+		createBundle(BUNDLE_B, "1.0.0", headers);
+	}
+	
+	private static void createApplicationA() throws IOException {
+		createApplicationAManifest();
+		createSubsystem(APPLICATION_A, BUNDLE_A);
+	}
+	
+	private static void createApplicationAManifest() throws IOException {
+		Map<String, String> attributes = new HashMap<String, String>();
+		attributes.put(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME, APPLICATION_A);
+		attributes.put(SubsystemConstants.SUBSYSTEM_CONTENT, BUNDLE_A);
+		createManifest(APPLICATION_A + ".mf", attributes);
+	}
+	
 	private static void createApplication(String name, String[] content) throws Exception {
 		ZipFixture feature = ArchiveFixture
 				.newZip()
@@ -120,6 +174,25 @@ public class ApplicationTest extends Sub
     	}
     }
     
+    @Test
+    public void testRequireCapability() throws Exception {
+    	File file = new File(BUNDLE_B);
+    	Bundle b = getRootSubsystem().getBundleContext().installBundle(file.toURI().toString(), new FileInputStream(file));
+    	try {
+	    	Subsystem application = installSubsystemFromFile(APPLICATION_A);
+	    	try {
+	    		startSubsystem(application);
+	    	}
+	    	finally {
+	    		stopSubsystem(application);
+	    		uninstallScopedSubsystem(application);
+	    	}
+    	}
+    	finally {
+    		b.uninstall();
+    	}
+    }
+    
     private byte[] createTestBundle3Content() throws IOException {
     	Manifest manifest = new Manifest();
     	manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");

Modified: aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/CompositeTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/CompositeTest.java?rev=1297302&r1=1297301&r2=1297302&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/CompositeTest.java (original)
+++ aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/CompositeTest.java Tue Mar  6 00:02:57 2012
@@ -1,14 +1,9 @@
 package org.apache.aries.subsystem.itests;
 
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Map.Entry;
 
-import org.apache.aries.unittest.fixture.ArchiveFixture;
-import org.apache.aries.unittest.fixture.ArchiveFixture.JarFixture;
-import org.apache.aries.unittest.fixture.ArchiveFixture.ManifestFixture;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -49,33 +44,6 @@ public class CompositeTest extends Subsy
 		createdTestFiles = true;
 	}
 	
-	private static void createBundle(String symbolicName) throws IOException {
-		createBundle(symbolicName, null);
-	}
-	
-	private static void createBundle(String symbolicName, Map<String, String> headers) throws IOException {
-		createBundle(symbolicName, null, headers);
-	}
-	
-	private static void createBundle(String symbolicName, String version, Map<String, String> headers) throws IOException {
-		if (headers == null)
-			headers = new HashMap<String, String>();
-		headers.put(Constants.BUNDLE_SYMBOLICNAME, symbolicName);
-		if (version != null)
-			headers.put(Constants.BUNDLE_VERSION, version);
-		createBundle(headers);
-	}
-	
-	private static void createBundle(Map<String, String> headers) throws IOException {
-		String symbolicName = headers.get(Constants.BUNDLE_SYMBOLICNAME);
-		JarFixture bundle = ArchiveFixture.newJar();
-		ManifestFixture manifest = bundle.manifest();
-		for (Entry<String, String> header : headers.entrySet()) {
-			manifest.attribute(header.getKey(), header.getValue());
-		}
-		write(symbolicName, bundle);
-	}
-	
 	private static void createBundleA() throws IOException {
 		Map<String, String> headers = new HashMap<String, String>();
 		headers.put(Constants.EXPORT_PACKAGE, PACKAGE_X + ";version=1.0");
@@ -158,18 +126,6 @@ public class CompositeTest extends Subsy
 		createManifest(COMPOSITE_D + ".mf", attributes);
 	}
 	
-	private static void createManifest(String name, Map<String, String> headers) throws IOException {
-		ManifestFixture manifest = ArchiveFixture.newJar().manifest();
-		for (Entry<String, String> header : headers.entrySet()) {
-			manifest.attribute(header.getKey(), header.getValue());
-		}
-		write(name, manifest);
-	}
-	
-	private static void createSubsystem(String name) throws IOException {
-		write(name, ArchiveFixture.newZip().binary("OSGI-INF/SUBSYSTEM.MF", new FileInputStream(name + ".mf")));
-	}
-	
 	@Test
 	public void testExportPackage() throws Exception {
 		Subsystem composite = installSubsystemFromFile(COMPOSITE_A);

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=1297302&r1=1297301&r2=1297302&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 Tue Mar  6 00:02:57 2012
@@ -36,6 +36,7 @@ import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 
 import junit.framework.Assert;
 
@@ -44,6 +45,9 @@ import org.apache.aries.subsystem.core.o
 import org.apache.aries.subsystem.itests.util.RepositoryGenerator;
 import org.apache.aries.subsystem.itests.util.Utils;
 import org.apache.aries.unittest.fixture.ArchiveFixture;
+import org.apache.aries.unittest.fixture.ArchiveFixture.JarFixture;
+import org.apache.aries.unittest.fixture.ArchiveFixture.ManifestFixture;
+import org.apache.aries.unittest.fixture.ArchiveFixture.ZipFixture;
 import org.apache.felix.bundlerepository.RepositoryAdmin;
 import org.ops4j.pax.exam.Option;
 import org.ops4j.pax.exam.container.def.PaxRunnerOptions;
@@ -300,6 +304,10 @@ public abstract class SubsystemTest exte
 		assertEquals("Wrong event type", type, event.getEventType());
 	}
 	
+	protected void assertHeaderExists(Subsystem subsystem, String name) {
+		assertNotNull("Missing header: " + name, subsystem.getSubsystemHeaders(null).get(name));
+	}
+	
 	protected void assertId(Subsystem subsystem) {
 		assertId(subsystem.getSubsystemId());
 	}
@@ -434,6 +442,55 @@ public abstract class SubsystemTest exte
 		assertEquals("Wrong version", expected, actual);
 	}
 	
+	protected static void createBundle(String symbolicName) throws IOException {
+		createBundle(symbolicName, null);
+	}
+	
+	protected static void createBundle(String symbolicName, Map<String, String> headers) throws IOException {
+		createBundle(symbolicName, null, headers);
+	}
+	
+	protected static void createBundle(String symbolicName, String version, Map<String, String> headers) throws IOException {
+		if (headers == null)
+			headers = new HashMap<String, String>();
+		headers.put(Constants.BUNDLE_SYMBOLICNAME, symbolicName);
+		if (version != null)
+			headers.put(Constants.BUNDLE_VERSION, version);
+		createBundle(headers);
+	}
+	
+	protected static void createBundle(Map<String, String> headers) throws IOException {
+		String symbolicName = headers.get(Constants.BUNDLE_SYMBOLICNAME);
+		JarFixture bundle = ArchiveFixture.newJar();
+		ManifestFixture manifest = bundle.manifest();
+		for (Entry<String, String> header : headers.entrySet()) {
+			manifest.attribute(header.getKey(), header.getValue());
+		}
+		write(symbolicName, bundle);
+	}
+	
+	protected static void createManifest(String name, Map<String, String> headers) throws IOException {
+		ManifestFixture manifest = ArchiveFixture.newJar().manifest();
+		for (Entry<String, String> header : headers.entrySet()) {
+			manifest.attribute(header.getKey(), header.getValue());
+		}
+		write(name, manifest);
+	}
+	
+	protected static void createSubsystem(String name) throws IOException {
+		createSubsystem(name, new String[0]);
+	}
+	
+	protected static void createSubsystem(String name, String...contents) throws IOException {
+		ZipFixture fixture = ArchiveFixture.newZip().binary("OSGI-INF/SUBSYSTEM.MF", new FileInputStream(name + ".mf"));
+		if (contents != null) {
+			for (String content : contents) {
+				fixture.binary(content, new FileInputStream(content));
+			}
+		}
+		write(name, fixture);
+	}
+	
 	protected Bundle getRegionContextBundle(Subsystem subsystem) {
 		BundleContext bc = subsystem.getBundleContext();
 		assertNotNull("No region context bundle", bc);