aries-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jwr...@apache.org
Subject svn commit: r1162585 [1/2] - in /aries/trunk/subsystem: subsystem-api/src/main/java/org/apache/ subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ subsystem-core/...
Date Sun, 28 Aug 2011 20:39:10 GMT
Author: jwross
Date: Sun Aug 28 20:39:09 2011
New Revision: 1162585

URL: http://svn.apache.org/viewvc?rev=1162585&view=rev
Log:
ARIES-737: Provide initial support for embedded subsystems.

Added:
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/obr/SubsystemResolver.java
    aries/trunk/subsystem/subsystem-itests/src/test/resources/application1/tb1.jar   (with props)
    aries/trunk/subsystem/subsystem-itests/src/test/resources/feature1/tb1.jar   (with props)
    aries/trunk/subsystem/subsystem-itests/src/test/resources/feature2/tb2.jar   (with props)
Modified:
    aries/trunk/subsystem/subsystem-api/src/main/java/org/apache/
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/AbstractAttribute.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Archive.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/BundleManifest.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DirectiveFactory.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ExportPackageHeader.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/HeaderFactory.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ImportPackageHeader.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Manifest.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ManifestVersionHeader.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ResolutionDirective.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemContentHeader.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/BundleEventHandler.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/OsgiIdentityCapability.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemBundleListener.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemFactory.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemManager.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/obr/ArchiveRepository.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/obr/SubsystemEnvironment.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/AbstractRuntimeResource.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/BundleResource.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/BundleRuntimeResource.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/ResourceFactory.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/ResourceListener.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/RuntimeResource.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/RuntimeResourceFactory.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/RuntimeResourceFactoryImpl.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/resource/SubsystemRuntimeResource.java
    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/java/org/apache/aries/subsystem/itests/util/Utils.java
    aries/trunk/subsystem/subsystem-itests/src/test/java/org/ops4j/pax/runner/platform/equinox/internal/SsActivator.java
    aries/trunk/subsystem/subsystem-itests/src/test/resources/feature1/OSGI-INF/SUBSYSTEM.MF

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/AbstractAttribute.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/AbstractAttribute.java?rev=1162585&r1=1162584&r2=1162585&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/AbstractAttribute.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/AbstractAttribute.java Sun Aug 28 20:39:09 2011
@@ -19,7 +19,7 @@ public abstract class AbstractAttribute 
 	}
 	
 	public StringBuilder appendToFilter(StringBuilder builder) {
-		return builder.append(getName()).append('=').append(getValue());
+		return builder.append('(').append(getName()).append('=').append(getValue()).append(')');
 	}
 
 	public String toString() {

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Archive.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Archive.java?rev=1162585&r1=1162584&r2=1162585&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Archive.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Archive.java Sun Aug 28 20:39:09 2011
@@ -23,20 +23,25 @@ import java.net.URL;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
 
 import org.apache.aries.subsystem.core.resource.ResourceFactory;
+import org.osgi.framework.wiring.Capability;
+import org.osgi.framework.wiring.Requirement;
 import org.osgi.framework.wiring.Resource;
+import org.osgi.service.repository.Repository;
 import org.osgi.service.subsystem.SubsystemException;
 
-public class Archive {
+public class Archive implements Repository {
 	private DeploymentManifest deploymentManifest;
 	private SubsystemManifest subsystemManifest;
 	
 //	private final DeploymentManifest deploymentManifest;
 	private final File directory;
-	private final Collection<Resource> resources = new ArrayList<Resource>();
+	private final Map<Resource, URL> resources = new HashMap<Resource, URL>();
 //	private final SubsystemManifest subsystemManifest;
 	
 	public Archive(String location, File dir, InputStream content) throws IOException, URISyntaxException {
@@ -90,6 +95,21 @@ public class Archive {
 //			deploymentManifest = new DeploymentManifest(file);
 //	}
 	
+	@Override
+	public Collection<Capability> findProviders(Requirement requirement) {
+		Collection<Capability> capabilities = new ArrayList<Capability>();
+		for (Resource resource : getResources())
+			for (Capability capability : resource.getCapabilities(requirement.getNamespace()))
+				if (requirement.matches(capability))
+					capabilities.add(capability);
+		return capabilities;
+	}
+
+	@Override
+	public URL getContent(Resource resource) {
+		return resources.get(resource);
+	}
+	
 	public synchronized DeploymentManifest getDeploymentManifest() {
 		return deploymentManifest;
 	}
@@ -103,7 +123,7 @@ public class Archive {
 	}
 	
 	public Collection<Resource> getResources() {
-		return Collections.unmodifiableCollection(resources);
+		return Collections.unmodifiableCollection(resources.keySet());
 	}
 	
 	public Collection<String> getResourceNames() {
@@ -209,7 +229,7 @@ public class Archive {
 	private void processResources() throws IOException, URISyntaxException {
 		for (String name : getResourceNames()) {
 			URL url = getURL(name);
-			resources.add(new ResourceFactory().newResource(url));
+			resources.put(new ResourceFactory().newResource(url), url);
 		}
 	}
 }

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/BundleManifest.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/BundleManifest.java?rev=1162585&r1=1162584&r2=1162585&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/BundleManifest.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/BundleManifest.java Sun Aug 28 20:39:09 2011
@@ -13,17 +13,8 @@
  */
 package org.apache.aries.subsystem.core.archive;
 
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.osgi.framework.Constants;
-
 public class BundleManifest extends Manifest {
-	public static final String IMPORT_PACKAGE = Constants.IMPORT_PACKAGE;
-	
-	public BundleManifest(InputStream in) throws IOException {
-		super(in);
+	public BundleManifest(java.util.jar.Manifest manifest) {
+		super(manifest);
 	}
-	
-	
 }

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DirectiveFactory.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DirectiveFactory.java?rev=1162585&r1=1162584&r2=1162585&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DirectiveFactory.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DirectiveFactory.java Sun Aug 28 20:39:09 2011
@@ -13,13 +13,12 @@
  */
 package org.apache.aries.subsystem.core.archive;
 
-import org.osgi.framework.Constants;
-
 public class DirectiveFactory {
 	public static Directive createDirective(String name, String value) {
-		if (Constants.RESOLUTION_DIRECTIVE.equals(name)) {
+		if (ResolutionDirective.NAME.equals(name))
 			return ResolutionDirective.getInstance(value);
-		}
+		if (StartOrderDirective.NAME.equals(name))
+			return new StartOrderDirective(value);
 		return new GenericDirective(name, value);
 	}
 }

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ExportPackageHeader.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ExportPackageHeader.java?rev=1162585&r1=1162584&r2=1162585&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ExportPackageHeader.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ExportPackageHeader.java Sun Aug 28 20:39:09 2011
@@ -13,5 +13,66 @@
  */
 package org.apache.aries.subsystem.core.archive;
 
-public class ExportPackageHeader {
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.osgi.framework.Constants;
+import org.osgi.framework.Version;
+import org.osgi.framework.wiring.Capability;
+import org.osgi.framework.wiring.Resource;
+import org.osgi.framework.wiring.ResourceConstants;
+
+public class ExportPackageHeader extends AbstractHeader {
+	public static final String NAME = Constants.EXPORT_PACKAGE;
+	
+	public ExportPackageHeader(String value) {
+		super(NAME, value);
+	}
+	
+	public List<Capability> getCapabilities(final Resource resource) {
+		List<Capability> capabilities = new ArrayList<Capability>(clauses.size());
+		for (final Clause clause : clauses) {
+			String[] exportedPackages = clause.getPath().split(";");
+			for (final String exportedPackage : exportedPackages) {
+				capabilities.add(new Capability() {
+					@Override
+					public String getNamespace() {
+						return ResourceConstants.WIRING_PACKAGE_NAMESPACE;
+					}
+
+					@Override
+					public Map<String, String> getDirectives() {
+						Collection<Directive> directives = clause.getDirectives();
+						Map<String, String> result = new HashMap<String, String>(directives.size());
+						for (Directive directive : directives)
+							result.put(directive.getName(), directive.getValue());
+						return result;
+					}
+
+					@Override
+					public Map<String, Object> getAttributes() {
+						Collection<Attribute> attributes = clause.getAttributes();
+						Map<String, Object> result = new HashMap<String, Object>(attributes.size() + 1);
+						for (Attribute attribute : attributes)
+							result.put(attribute.getName(), attribute.getValue());
+						// Add the namespace attribute.
+						result.put(ResourceConstants.WIRING_PACKAGE_NAMESPACE, exportedPackage);
+						// Add the default version, if necessary.
+						if (result.get(Constants.VERSION_ATTRIBUTE) == null)
+							result.put(Constants.VERSION_ATTRIBUTE, Version.emptyVersion);
+						return result;
+					}
+
+					@Override
+					public Resource getResource() {
+						return resource;
+					}
+				});
+			}
+		}
+		return capabilities;
+	}
 }

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/HeaderFactory.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/HeaderFactory.java?rev=1162585&r1=1162584&r2=1162585&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/HeaderFactory.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/HeaderFactory.java Sun Aug 28 20:39:09 2011
@@ -85,9 +85,12 @@ public class HeaderFactory {
 			return new SubsystemVersionHeader(value);
 		if (name.equals(SubsystemContentHeader.NAME))
 			return new SubsystemContentHeader(value);
-		// TODO Add to constants.
 		if (name.equals(SubsystemTypeHeader.NAME))
 			return new SubsystemTypeHeader(value);
+		if (ExportPackageHeader.NAME.equals(name))
+			return new ExportPackageHeader(value);
+		if (ImportPackageHeader.NAME.equals(name))
+			return new ImportPackageHeader(value);
 		return new GenericHeader(name, value);
 			
 	}

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ImportPackageHeader.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ImportPackageHeader.java?rev=1162585&r1=1162584&r2=1162585&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ImportPackageHeader.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ImportPackageHeader.java Sun Aug 28 20:39:09 2011
@@ -65,7 +65,7 @@ public class ImportPackageHeader impleme
 			if (directive == null) {
 				StringBuilder builder = new StringBuilder("(&");
 				for (Attribute a : getAttributes()) {
-					a.appendToFilter(builder.append('(')).append(')');
+					a.appendToFilter(builder);
 				}
 				directive = new GenericDirective(Constants.FILTER_DIRECTIVE, builder.append(')').toString());
 				myParameters.put(directive.getName(), directive);
@@ -186,6 +186,8 @@ public class ImportPackageHeader impleme
 		}
 	}
 	
+	public static final String NAME = Constants.IMPORT_PACKAGE;
+	
 	private static final String REGEX = '(' + Grammar.IMPORT + ")(?:\\,(" + Grammar.IMPORT + "))*";
 	private static final Pattern PATTERN = Pattern.compile(REGEX);
 	

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Manifest.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Manifest.java?rev=1162585&r1=1162584&r2=1162585&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Manifest.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Manifest.java Sun Aug 28 20:39:09 2011
@@ -31,11 +31,17 @@ public abstract class Manifest {
 	protected final java.util.jar.Manifest manifest;
 	
 	public Manifest(InputStream in) throws IOException {
-		manifest = ManifestProcessor.parseManifest(in);
+		this(ManifestProcessor.parseManifest(in));
+	}
+	
+	public Manifest(java.util.jar.Manifest manifest) {
+		this.manifest = manifest;
 		for (Map.Entry<Object, Object> entry : manifest.getMainAttributes().entrySet()) {
 			Header header = HeaderFactory.createHeader(String.valueOf(entry.getKey()), String.valueOf(entry.getValue()));
 			headers.put(header.getName(), header);
 		}
+		if (headers.get(ManifestVersionHeader.NAME) == null)
+			headers.put(ManifestVersionHeader.NAME, ManifestVersionHeader.DEFAULT);
 	}
 	
 	public Manifest(File manifestFile) throws IOException {

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ManifestVersionHeader.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ManifestVersionHeader.java?rev=1162585&r1=1162584&r2=1162585&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ManifestVersionHeader.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ManifestVersionHeader.java Sun Aug 28 20:39:09 2011
@@ -19,6 +19,8 @@ public class ManifestVersionHeader exten
 	public static final String DEFAULT_VALUE = "1.0";
 	public static final String NAME = Attributes.Name.MANIFEST_VERSION.toString();
 	
+	public static final ManifestVersionHeader DEFAULT = new ManifestVersionHeader(DEFAULT_VALUE);
+	
 	public ManifestVersionHeader() {
 		this(DEFAULT_VALUE);
 	}

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ResolutionDirective.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ResolutionDirective.java?rev=1162585&r1=1162584&r2=1162585&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ResolutionDirective.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ResolutionDirective.java Sun Aug 28 20:39:09 2011
@@ -16,7 +16,7 @@ package org.apache.aries.subsystem.core.
 import org.osgi.framework.Constants;
 
 public class ResolutionDirective extends AbstractDirective {
-	public static final String NAME = "resolution";
+	public static final String NAME = Constants.RESOLUTION_DIRECTIVE;
 	
 	public static final ResolutionDirective MANDATORY = new ResolutionDirective(true);
 	public static final ResolutionDirective OPTIONAL = new ResolutionDirective(false);
@@ -37,7 +37,7 @@ public class ResolutionDirective extends
 	private final boolean mandatory;
 	
 	private ResolutionDirective(boolean mandatory) {
-		super(Constants.RESOLUTION_DIRECTIVE, mandatory ? Constants.RESOLUTION_MANDATORY : Constants.RESOLUTION_OPTIONAL);
+		super(NAME, mandatory ? Constants.RESOLUTION_MANDATORY : Constants.RESOLUTION_OPTIONAL);
 		this.mandatory = mandatory;
 	}
 

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemContentHeader.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemContentHeader.java?rev=1162585&r1=1162584&r2=1162585&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemContentHeader.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemContentHeader.java Sun Aug 28 20:39:09 2011
@@ -16,6 +16,8 @@ package org.apache.aries.subsystem.core.
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
 
 import org.osgi.framework.Constants;
 import org.osgi.framework.Version;
@@ -25,20 +27,26 @@ public class SubsystemContentHeader exte
 	public static class Content {
 		private final boolean mandatory;
 		private final String name;
+		private final int startOrder;
 		private final String type;
 		private final VersionRange versionRange;
 		
-		public Content(boolean mandatory, String name, String type, VersionRange versionRange) {
+		public Content(boolean mandatory, String name, String type, VersionRange versionRange, int startOrder) {
 			this.mandatory = mandatory;
 			this.name = name;
 			this.type = type;
 			this.versionRange = versionRange;
+			this.startOrder = startOrder;
 		}
 		
 		public String getName() {
 			return name;
 		}
 		
+		public int getStartOrder() {
+			return startOrder;
+		}
+		
 		public String getType() {
 			return type;
 		}
@@ -65,6 +73,10 @@ public class SubsystemContentHeader exte
 				.append(ResolutionDirective.NAME)
 				.append(":=")
 				.append(isMandatory())
+				.append(';')
+				.append(StartOrderDirective.NAME)
+				.append(":=")
+				.append(getStartOrder())
 				.toString();
 		}
 	}
@@ -72,7 +84,7 @@ public class SubsystemContentHeader exte
 	// TODO Add to constants.
 	public static final String NAME = "Subsystem-Content";
 	
-	private final Collection<Content> contents;
+	private final List<Content> contents;
 	
 	public SubsystemContentHeader(String value) {
 		super(NAME, value);
@@ -93,8 +105,18 @@ public class SubsystemContentHeader exte
 			if (attribute != null) {
 				versionRange = new VersionRange(attribute.getValue());
 			}
-			contents.add(new Content(mandatory, name, type, versionRange));
+			int startOrder = StartOrderDirective.DEFAULT_VALUE;
+			directive = clause.getDirective(StartOrderDirective.NAME);
+			if (directive != null)
+				startOrder = ((StartOrderDirective)directive).getStartOrder();
+			contents.add(new Content(mandatory, name, type, versionRange, startOrder));
 		}
+		Collections.sort(contents, new Comparator<Content>() {
+			@Override
+			public int compare(Content content1, Content content2) {
+				return ((Integer)content1.getStartOrder()).compareTo(content2.getStartOrder());
+			}
+		});
 	}
 
 	public Collection<Content> getContents() {

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=1162585&r1=1162584&r2=1162585&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 Sun Aug 28 20:39:09 2011
@@ -15,17 +15,12 @@ package org.apache.aries.subsystem.core.
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.Dictionary;
-import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.List;
-import java.util.Map;
 import java.util.concurrent.Executor;
 
-import org.apache.aries.subsystem.core.obr.felix.FelixResourceAdapter;
-import org.apache.aries.subsystem.core.obr.felix.OsgiResourceAdapter;
-import org.apache.felix.bundlerepository.Reason;
+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;
@@ -35,21 +30,14 @@ import org.osgi.framework.InvalidSyntaxE
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.framework.hooks.resolver.ResolverHookFactory;
-import org.osgi.framework.wiring.Capability;
 import org.osgi.framework.wiring.FrameworkWiring;
-import org.osgi.framework.wiring.Requirement;
-import org.osgi.framework.wiring.Resource;
-import org.osgi.framework.wiring.Wire;
 import org.osgi.service.coordinator.Coordinator;
 import org.osgi.service.event.EventAdmin;
 import org.osgi.service.event.EventConstants;
 import org.osgi.service.event.EventHandler;
 import org.osgi.service.repository.Repository;
-import org.osgi.service.resolver.Environment;
-import org.osgi.service.resolver.ResolutionException;
 import org.osgi.service.resolver.Resolver;
 import org.osgi.service.subsystem.Subsystem;
-import org.osgi.service.subsystem.SubsystemException;
 import org.osgi.util.tracker.ServiceTracker;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -62,7 +50,6 @@ public class Activator implements Bundle
 	private static final Logger LOGGER = LoggerFactory.getLogger(Activator.class);
 
 	private static BundleContext context;
-	private static SubsystemManager subsystemManager = new SubsystemManager();
 	
 	public static BundleContext getBundleContext() {
 		return context;
@@ -129,59 +116,56 @@ public class Activator implements Bundle
 	 * A naive implementation serving as a placeholder until a real Resolver comes along.
 	 */
 	public static Resolver getResolver() {
-		return new Resolver() {
-			@Override
-			public Map<Resource, List<Wire>> resolve(Environment environment, Requirement... requirements) throws ResolutionException {
-				Collection<Capability> capabilities = new ArrayList<Capability>();
-				for (Requirement requirement : requirements)
-					capabilities.addAll(environment.findProviders(requirement));
-				List<Resource> resources = new ArrayList<Resource>(capabilities.size());
-				for (Capability capability : capabilities)
-					resources.add(capability.getResource());
-				org.apache.felix.bundlerepository.Resolver resolver = getRepositoryAdmin().resolver();
-		        for (Resource resource : resources)
-		            resolver.add(new OsgiResourceAdapter(resource));
-		        if (resolver.resolve()) {
-		        	/* 
-		        	 * TODO For now, these need to go back through the environment in order to be sure the URL is available.
-		        	 * This is because RepositoryAdmin is not going through the environment as part of pulling in transitive
-		        	 * dependencies. Once a "real" Resolver is available, this will no longer be necessary.
-		        	 */
-		        	for (org.apache.felix.bundlerepository.Resource resource : resolver.getRequiredResources()) {
-		        		Resource r = new FelixResourceAdapter(resource);
-		        		// Make the environment aware of the resource and its URL.
-		        		environment.findProviders(new OsgiIdentityRequirement(r, true));
-		            	resources.add(r);
-		        	}
-		        	for (org.apache.felix.bundlerepository.Resource resource : resolver.getOptionalResources()) {
-		        		Resource r = new FelixResourceAdapter(resource);
-		        		// Make the environment aware of the resource and its URL.
-		        		environment.findProviders(new OsgiIdentityRequirement(r, true));
-		            	resources.add(r);
-		        	}
-		        }
-		        else {
-		            Reason[] reasons = resolver.getUnsatisfiedRequirements();
-		            StringBuilder builder = new StringBuilder("Failed to resolve subsystem").append(System.getProperty("line.separator"));
-		            for (Reason reason : reasons)
-		                builder
-		                	.append("resource = ")
-		                	.append(reason.getResource().getSymbolicName())
-		                	.append(", requirement = ")
-		                	.append(reason.getRequirement().getName())
-		                	.append(System.getProperty("line.separator"));
-		            throw new SubsystemException(builder.toString());
-		        }
-		        Map<Resource, List<Wire>> result = new HashMap<Resource, List<Wire>>(resources.size());
-				for (Resource resource : resources)
-					result.put(resource, Collections.EMPTY_LIST);
-				return result;
-			}
-		};
-	}
-	
-	public static SubsystemManager getSubsystemManager() {
-		return subsystemManager;
+		return new SubsystemResolver();
+//		return new Resolver() {
+//			@Override
+//			public Map<Resource, List<Wire>> resolve(Environment environment, Requirement... requirements) throws ResolutionException {
+//				Collection<Capability> capabilities = new ArrayList<Capability>();
+//				for (Requirement requirement : requirements)
+//					capabilities.addAll(environment.findProviders(requirement));
+//				List<Resource> resources = new ArrayList<Resource>(capabilities.size());
+//				for (Capability capability : capabilities)
+//					resources.add(capability.getResource());
+//				org.apache.felix.bundlerepository.Resolver resolver = getRepositoryAdmin().resolver();
+//		        for (Resource resource : resources)
+//		            resolver.add(new OsgiResourceAdapter(resource));
+//		        if (resolver.resolve()) {
+//		        	/* 
+//		        	 * TODO For now, these need to go back through the environment in order to be sure the URL is available.
+//		        	 * This is because RepositoryAdmin is not going through the environment as part of pulling in transitive
+//		        	 * dependencies. Once a "real" Resolver is available, this will no longer be necessary.
+//		        	 */
+//		        	for (org.apache.felix.bundlerepository.Resource resource : resolver.getRequiredResources()) {
+//		        		Resource r = new FelixResourceAdapter(resource);
+//		        		// Make the environment aware of the resource and its URL.
+//		        		environment.findProviders(new OsgiIdentityRequirement(r, true));
+//		            	resources.add(r);
+//		        	}
+//		        	for (org.apache.felix.bundlerepository.Resource resource : resolver.getOptionalResources()) {
+//		        		Resource r = new FelixResourceAdapter(resource);
+//		        		// Make the environment aware of the resource and its URL.
+//		        		environment.findProviders(new OsgiIdentityRequirement(r, true));
+//		            	resources.add(r);
+//		        	}
+//		        }
+//		        else {
+//		            Reason[] reasons = resolver.getUnsatisfiedRequirements();
+//		            StringBuilder builder = new StringBuilder("Failed to resolve subsystem").append(System.getProperty("line.separator"));
+//		            for (Reason reason : reasons)
+//		                builder
+//		                	.append("resource = ")
+//		                	.append(reason.getResource().getSymbolicName())
+//		                	.append(", requirement = ")
+//		                	.append(reason.getRequirement().getName())
+//		                	.append(System.getProperty("line.separator"));
+//		            throw new SubsystemException(builder.toString());
+//		        }
+//		        Map<Resource, List<Wire>> result = new HashMap<Resource, List<Wire>>(resources.size());
+//				for (Resource resource : resources)
+//					result.put(resource, Collections.EMPTY_LIST);
+//				return result;
+//			}
+//		};
 	}
 	
 	private final BundleListener bundleListener = new SubsystemSynchronousBundleListener();

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=1162585&r1=1162584&r2=1162585&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 Sun Aug 28 20:39:09 2011
@@ -14,20 +14,25 @@
 package org.apache.aries.subsystem.core.internal;
 
 import java.io.File;
+import java.io.IOException;
 import java.io.InputStream;
+import java.net.URISyntaxException;
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.MissingResourceException;
 import java.util.ResourceBundle;
 import java.util.Set;
 
+import org.apache.aries.subsystem.core.ResourceHelper;
 import org.apache.aries.subsystem.core.archive.Archive;
 import org.apache.aries.subsystem.core.archive.DeployedContentHeader;
 import org.apache.aries.subsystem.core.archive.DeployedContentHeader.DeployedContent;
@@ -39,45 +44,49 @@ import org.apache.aries.subsystem.core.a
 import org.apache.aries.subsystem.core.archive.SubsystemSymbolicNameHeader;
 import org.apache.aries.subsystem.core.archive.VersionHeader;
 import org.apache.aries.subsystem.core.obr.SubsystemEnvironment;
-import org.apache.aries.subsystem.core.resource.BundleRuntimeResource;
-import org.apache.aries.subsystem.core.resource.RuntimeResource;
-import org.apache.aries.subsystem.core.resource.RuntimeResourceFactoryImpl;
 import org.eclipse.equinox.region.Region;
 import org.eclipse.equinox.region.RegionFilter;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleEvent;
 import org.osgi.framework.BundleException;
 import org.osgi.framework.Version;
+import org.osgi.framework.wiring.BundleRevision;
 import org.osgi.framework.wiring.Capability;
+import org.osgi.framework.wiring.Requirement;
 import org.osgi.framework.wiring.Resource;
+import org.osgi.framework.wiring.ResourceConstants;
 import org.osgi.service.coordinator.Coordination;
 import org.osgi.service.coordinator.CoordinationException;
+import org.osgi.service.coordinator.Participant;
 import org.osgi.service.event.Event;
 import org.osgi.service.event.EventAdmin;
 import org.osgi.service.event.EventConstants;
 import org.osgi.service.subsystem.Subsystem;
 import org.osgi.service.subsystem.SubsystemConstants;
 import org.osgi.service.subsystem.SubsystemException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-public class AriesSubsystem implements Subsystem {
-	public static AriesSubsystem newInstance(String location, InputStream content, AriesSubsystem parent) throws Exception {
-		AriesSubsystem subsystem = new AriesSubsystem(location, content, parent);
-		Archive archive = subsystem.getArchive();
-		subsystem.environment = new SubsystemEnvironment(subsystem);
-		if (archive.getSubsystemManifest() == null) {
-			SubsystemUri uri = new SubsystemUri(location);
-			archive.setSubsystemManifest(SubsystemManifest.newInstance(uri.getSymbolicName(), uri.getVersion(), archive.getResources()));
-		}
-		if (archive.getDeploymentManifest() == null) {
-			archive.setDeploymentManifest(DeploymentManifest.newInstance(archive.getSubsystemManifest(), subsystem.environment));
-		}
-		return subsystem;
-	}
-	
+public class AriesSubsystem implements Subsystem, Resource {
+	private static final Logger LOGGER = LoggerFactory.getLogger(AriesSubsystem.class);
 	private static final String ROOT_LOCATION = "root";
 	private static final String ROOT_SYMBOLIC_NAME = "org.apache.aries.subsystem.root";
 	private static final Version ROOT_VERSION = Version.parseVersion("1.0.0");
 	
+	private static final Map<String, AriesSubsystem> locationToSubsystem = new HashMap<String, AriesSubsystem>();
+	private static final Map<Resource, Set<Subsystem>> resourceToSubsystems = new HashMap<Resource, Set<Subsystem>>();
+	
+	static synchronized Collection<AriesSubsystem> getSubsystems(Resource resource) {
+		ArrayList<AriesSubsystem> result = new ArrayList<AriesSubsystem>(locationToSubsystem.size());
+		for (AriesSubsystem subsystem : locationToSubsystem.values()) {
+			if (subsystem.contains(resource)) {
+				result.add(subsystem);
+			}
+		}
+		result.trimToSize();
+		return result;
+	}
+	
 	private static long lastId;
 	
 	private static void deleteFile(File file) {
@@ -109,8 +118,14 @@ public class AriesSubsystem implements S
 			Map<String, Object> map = new HashMap<String, Object>();
 			map.put(SubsystemConstants.SUBSYSTEM_ID, subsystem.getSubsystemId());
 			map.put(SubsystemConstants.SUBSYSTEM_LOCATION, subsystem.getLocation());
-			map.put(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME, subsystem.getSymbolicName());
-			map.put(SubsystemConstants.SUBSYSTEM_VERSION, String.valueOf(subsystem.getVersion()));
+			try {
+				map.put(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME, subsystem.getSymbolicName());
+			}
+			catch (IllegalStateException e) {}
+			try {
+				map.put(SubsystemConstants.SUBSYSTEM_VERSION, String.valueOf(subsystem.getVersion()));
+			}
+			catch (IllegalStateException e) {}
 			// TODO This needs to be defined as a constant.
 			map.put("subsystem.state", String.valueOf(subsystem.getState()));
 			map.put(EventConstants.TIMESTAMP, System.currentTimeMillis());
@@ -125,15 +140,15 @@ public class AriesSubsystem implements S
 		}
 	}
 	
-	private final Archive archive;
 	private final Set<Resource> constituents = Collections.synchronizedSet(new HashSet<Resource>());
-	private final Set<AriesSubsystem> children = new HashSet<AriesSubsystem>();
+	private final Set<AriesSubsystem> children = Collections.synchronizedSet(new HashSet<AriesSubsystem>());
 	private volatile SubsystemEnvironment environment;
 	private final long id;
 	private final String location;
 	private final AriesSubsystem parent;
-	private final Region region;
 	
+	private Archive archive;
+	private Region region;
 	private Subsystem.State state;
 	
 	public AriesSubsystem() throws Exception {
@@ -147,32 +162,10 @@ public class AriesSubsystem implements S
 		environment = null;
 	}
 	
-	private AriesSubsystem(String location, InputStream content, AriesSubsystem parent) throws Exception {
+	private AriesSubsystem(String location, /*InputStream content,*/ AriesSubsystem parent) /*throws Exception*/ {
 		this.location = location;
 		this.parent = parent;
-		if (content == null) {
-			content = new URL(location).openStream();
-		}
-		File rootDirectory = Activator.getBundleContext().getDataFile("");
 		id = getNextId();
-		File subsystemDirectory = new File(rootDirectory, "subsystem" + id + System.getProperty("file.separator"));
-		// TODO Leaking reference. Issues?
-//		environment = new SubsystemEnvironment(this);
-//		archive = new Archive(location, subsystemDirectory, content, environment);
-		archive = new Archive(location, subsystemDirectory, content);
-		if (isFeature()) {
-			// Features do not have regions.
-			region = null;
-		}
-		else {
-			// Applications and composites have regions.
-			region = createRegion();
-		}
-		
-	}
-	
-	public void addConstituent(Resource resource) {
-		constituents.add(resource);
 	}
 	
 	@Override
@@ -180,10 +173,16 @@ public class AriesSubsystem implements S
 		// TODO Auto-generated method stub
 	}
 	
-	public Archive getArchive() {
+	public synchronized Archive getArchive() {
 		return archive;
 	}
 	
+	@Override
+	public List<Capability> getCapabilities(String namespace) {
+		Capability capability = new OsgiIdentityCapability(this, getSymbolicName(), getVersion(), "osgi.subsystem");
+		return Arrays.asList(new Capability[]{capability});
+	}
+
 	@SuppressWarnings({ "unchecked", "rawtypes" })
 	public Collection<Subsystem> getChildren() {
 		return (Collection<Subsystem>)(Collection)Collections.unmodifiableSet(children);
@@ -191,10 +190,36 @@ public class AriesSubsystem implements S
 
 	@Override
 	public Collection<Resource> getConstituents() {
-		return Collections.unmodifiableSet(constituents);
+		/* 
+		 * TODO The definition of constituents needs to be worked out from both a design and implementation perspective.
+		 * (1) In general, any Resource type except for osgi.subsystem.
+		 * (2) A transitive dependency if this is the root subsystem or provision-policy:=acceptTransitive.
+		 * (3) A content Resource of this subsystem if the Resource is not also a subsystem (also, doesn't apply to 
+		 *     the root subsystem since it has no content resources).
+		 * (4) A bundle Resource installed into a region by means other than the subsystem API (primarily for the 
+		 *     root subsystem which shares the kernel region but could apply to any subsystem).
+		 * (5) Caution with 4: this does not include feature content resources installed into a non-feature subsystem region. 
+		 *     These are constituents of the feature itself.
+		 */
+		if (isRoot()) {
+			// TODO This does not take into account the possibility that resource types other than bundle became part of the root subsystem.
+			Set<Long> bundleIds = region.getBundleIds();
+			Collection<Resource> resources = new ArrayList<Resource>(bundleIds.size());
+			for (Long bundleId : bundleIds)
+				resources.add(Activator.getBundleContext().getBundle(bundleId).adapt(BundleRevision.class));
+			return resources;
+		}
+		return Collections.unmodifiableCollection(constituents);
 	}
 	
-	public SubsystemEnvironment getEnvironment() {
+	public DeploymentManifest getDeploymentManifest() throws IOException {
+		if (archive.getDeploymentManifest() == null) {
+			archive.setDeploymentManifest(DeploymentManifest.newInstance(archive.getSubsystemManifest(), environment));
+		}
+		return archive.getDeploymentManifest();
+	}
+	
+	public synchronized SubsystemEnvironment getEnvironment() {
 		return environment;
 	}
 
@@ -219,7 +244,7 @@ public class AriesSubsystem implements S
 		Map<String, String> result = new HashMap<String, String>(headers.size());
 		for (Header header : headers) {
 			String value = header.getValue();
-			if (value.startsWith("%")) {
+			if (rb != null && value.startsWith("%")) {
 				value = value.substring(1);
 				String translation = null;
 				try {
@@ -243,9 +268,10 @@ public class AriesSubsystem implements S
 	public AriesSubsystem getParent() {
 		return parent;
 	}
-	
-	public Region getRegion() {
-		return region;
+
+	@Override
+	public List<Requirement> getRequirements(String namespace) {
+		return Collections.emptyList();
 	}
 
 	@Override
@@ -261,6 +287,11 @@ public class AriesSubsystem implements S
 	@Override
 	public String getSymbolicName() {
 		if (archive == null) {
+			// If the archive is null, this is either the root subsystem or an installing subsystem not yet initialized.
+			if (State.INSTALLING.equals(getState()))
+				// The root subsystem's state will never be INSTALLING, so this is an uninitialized subsystem.
+				throw new IllegalStateException();
+			// This is the root subsystem.
 			return ROOT_SYMBOLIC_NAME;
 		}
 		return ((SubsystemSymbolicNameHeader)archive.getSubsystemManifest().getSubsystemSymbolicName()).getSymbolicName();
@@ -269,6 +300,11 @@ public class AriesSubsystem implements S
 	@Override
 	public Version getVersion() {
 		if (archive == null) {
+			// If the archive is null, this is either the root subsystem or an installing subsystem not yet initialized.
+			if (State.INSTALLING.equals(getState()))
+				// The root subsystem's state will never be INSTALLING, so this is an uninitialized subsystem.
+				throw new IllegalStateException();
+			// This is the root subsystem.
 			return ROOT_VERSION;
 		}
 		return ((VersionHeader)archive.getSubsystemManifest().getSubsystemVersion()).getVersion();
@@ -280,21 +316,23 @@ public class AriesSubsystem implements S
 	}
 	
 	@Override
-	public Subsystem install(String location, InputStream content) throws SubsystemException {
+	public synchronized Subsystem install(String location, final InputStream content) throws SubsystemException {
 		final AriesSubsystem subsystem;
-		try {
-			subsystem = Activator.getSubsystemManager().newSubsystem(location, content, this);
-		}
-		catch (Exception e) {
-			throw new SubsystemException(e);
-		}
-		children.add(subsystem);
+		if (locationToSubsystem.containsKey(location))
+			return locationToSubsystem.get(location);
+		subsystem = new AriesSubsystem(location, this);
+		locationToSubsystem.put(location, subsystem);
 		subsystem.setState(Subsystem.State.INSTALLING);
 		postEvent(subsystem, SubsystemConstants.EventType.INSTALLING);
+		children.add(subsystem);
+		constituents.add(subsystem);
 		Activator.getExecutor().execute(new Runnable() {
 			public void run() {
 				try {
-					subsystem.installAsync();
+					subsystem.initialize(content);
+					subsystem.install();
+					subsystem.setState(Subsystem.State.INSTALLED);
+					postEvent(subsystem, SubsystemConstants.EventType.INSTALLED);
 				}
 				catch (Exception e) {
 					postEvent(subsystem, SubsystemConstants.EventType.FAILED, e);
@@ -321,11 +359,8 @@ public class AriesSubsystem implements S
 		return "osgi.feature".equals(archive.getSubsystemManifest().getSubsystemType().getValue());
 	}
 	
-	public boolean isTransitive(Resource resource) {
-		SubsystemEnvironment environment = getEnvironment();
-		if (environment == null)
-			return true;
-		return !environment.isContentResource(resource);
+	public void removeConstituent(Resource resource) {
+		constituents.remove(resource);
 	}
 	
 	/* INSTALLING	Wait, Start
@@ -364,7 +399,52 @@ public class AriesSubsystem implements S
 		}
 		Activator.getExecutor().execute(new Runnable() {
 			public void run() {
-				startAsync();
+				// TODO Need to hold a lock here to guarantee that another start operation can't occur when the state goes to RESOLVED.
+				// Resolve the subsystem, if necessary.
+				if (getState() == State.RESOLVING) { // Otherwise, the state will be STARTING.
+					try {
+						setImportIsolationPolicy();
+						// TODO I think this is insufficient. Do we need both pre-install and post-install environments for the Resolver?
+						if (!Activator.getFrameworkWiring().resolveBundles(getBundles())) {
+							throw new Exception("Framework could not resolve the bundles");
+						}
+						setExportIsolationPolicy();
+						// TODO Could avoid calling setState (and notifyAll) here and avoid the need for a lock.
+						setState(State.RESOLVED);
+						postEvent(AriesSubsystem.this, SubsystemConstants.EventType.RESOLVED);
+						setState(State.STARTING);
+						postEvent(AriesSubsystem.this, SubsystemConstants.EventType.STARTING);
+					}
+					catch (Exception e) {
+						setState(State.INSTALLED);
+						postEvent(AriesSubsystem.this, SubsystemConstants.EventType.FAILED, e);
+						return;
+					}
+				}
+				// Start the subsystem.
+				Coordination coordination = Activator.getCoordinator().create(getSymbolicName() + '-' + getSubsystemId(), 0);
+				try {
+					// TODO Need to make sure the consitutents are ordered by start level.
+					for (Resource resource : constituents) {
+						startResource(resource, coordination);
+					}
+					setState(State.ACTIVE);
+					postEvent(AriesSubsystem.this, SubsystemConstants.EventType.STARTED);
+				}
+				catch (Exception e) {
+					coordination.fail(e);
+					// TODO Need to reinstate complete isolation by disconnecting the region and transition to INSTALLED.
+				}
+				finally {
+					try {
+						coordination.end();
+					}
+					catch (CoordinationException e) {
+						LOGGER.error("An error occurred while starting in a resource in subsystem " + this, e);
+						setState(State.RESOLVED);
+						postEvent(AriesSubsystem.this, SubsystemConstants.EventType.FAILED, e);
+					}
+				}
 			}
 		});
 	}
@@ -398,7 +478,20 @@ public class AriesSubsystem implements S
 		// TODO Need to store the task for cancellation.
 		Activator.getExecutor().execute(new Runnable() {
 			public void run() {
-				stopAsync();
+				// TODO Persist stop state.
+				for (Resource resource : constituents) {
+					try {
+						stopResource(resource);
+					}
+					catch (Exception e) {
+						LOGGER.error("An error occurred while stopping resource " + resource + " of subsystem " + this, e);
+						// TODO Should FAILED go out for each failure?
+						postEvent(AriesSubsystem.this, SubsystemConstants.EventType.FAILED, e);
+					}
+				}
+				// TODO Can we automatically assume it actually is resolved?
+				setState(State.RESOLVED);
+				postEvent(AriesSubsystem.this, SubsystemConstants.EventType.STOPPED);
 			}
 		});
 	}
@@ -433,7 +526,23 @@ public class AriesSubsystem implements S
 		postEvent(this, SubsystemConstants.EventType.UNINSTALLING);
 		Activator.getExecutor().execute(new Runnable() {
 			public void run() {
-				uninstallAsync();
+				for (Iterator<Resource> iterator = constituents.iterator(); iterator.hasNext();) {
+					Resource resource = iterator.next();
+					try {
+						uninstallResource(resource);
+					}
+					catch (Exception e) {
+						LOGGER.error("An error occurred while uninstalling resource " + resource + " of subsystem " + this, e);
+						// TODO Should FAILED go out for each failure?
+						postEvent(AriesSubsystem.this, SubsystemConstants.EventType.FAILED, e);
+					}
+					iterator.remove();
+				}
+				parent.children.remove(AriesSubsystem.this);
+				locationToSubsystem.remove(location);
+				deleteFile(Activator.getBundleContext().getDataFile("subsystem" + id + System.getProperty("file.separator")));
+				setState(State.UNINSTALLED);
+				postEvent(AriesSubsystem.this, SubsystemConstants.EventType.UNINSTALLED);
 			}
 		});
 	}
@@ -465,56 +574,11 @@ public class AriesSubsystem implements S
 		return constituents.contains(resource);
 	}
 	
-//	protected Resource findContentResource(String namespace, String symbolicName, String version) {
-//		Requirement requirement = new OsgiIdentityRequirement(null, symbolicName, Version.parseVersion(version), namespace);
-//		Resource result = null;
-//		/* Root */
-//		if (isRoot()) {
-//			// For the root subsystem, simply look for a resource in the system repository.
-//			result = ResourceHelper.getResource(requirement, repository);
-//		}
-//		/* Features */
-//		else if (isFeature()) {
-//			// Check for existing, accessible resources first.
-//			result = parent.findContentResource(namespace, symbolicName, version);
-//			// If necessary, look for the resource in the subsystem repository.
-//			if (result == null) {
-//				if (repository != null) {
-//					// Repository will be null if the subsystem contained no resources.
-//					result = ResourceHelper.getResource(requirement, repository);
-//				}
-//				// Finally, if necessary, look for the resource in other repositories.
-//				if (result == null) {
-//					result = Activator.getResourceResolver().find(symbolicName + ";version=" + version);
-//				}
-//			}
-//			
-//		}
-//		/* Applications */
-//		else if (isApplication()) {
-//			// For applications, we never want to reuse an existing resource.
-//			// Favor resources included with the subsystem definition.
-//			if (repository != null) {
-//				// Repository will be null if the subsystem contained no resources.
-//				result = ResourceHelper.getResource(requirement, repository);
-//			}
-//			// If necessary, look for the resource in other repositories.
-//			if (result == null) {
-//				result = Activator.getResourceResolver().find(symbolicName + ";version=" + version);
-//			}
-//		}
-//		/* Composites */
-//		else {
-//			// TODO Implement composite behavior.
-//		}
-//		return result;
-//	}
-	
 	protected Collection<Bundle> getBundles() {
 		ArrayList<Bundle> result = new ArrayList<Bundle>(constituents.size());
 		for (Resource resource : constituents) {
-			if (resource instanceof BundleRuntimeResource)
-				result.add(((BundleRuntimeResource)resource).getBundle());
+			if (resource instanceof BundleRevision)
+				result.add(((BundleRevision)resource).getBundle());
 		}
 		result.trimToSize();
 		return result;
@@ -542,80 +606,65 @@ public class AriesSubsystem implements S
 	
 	private Region createRegion() throws BundleException {
 		if (isRoot())
-			return Activator.getRegionDigraph().getRegion(0);
+			// The root subsystem's region should be the same one the subsystem bundle was installed into.
+			return Activator.getRegionDigraph().getRegion(Activator.getBundleContext().getBundle());
+		if (isFeature())
+			// Feature subsystems do not have regions because they are not isolated.
+			return null;
+		// All other subsystems get a dedicated region for isolation.
 		return Activator.getRegionDigraph().createRegion(getSymbolicName() + ';' + getVersion());
 	}
 	
-	private void install(Resource resource, Coordination coordination, boolean transitive) {
-//		String content = ResourceHelper.getContentAttribute(resource);
-//		String location = getSubsystemId() + '@' + getSymbolicName() + '@' + content;
-		try {
-//			final RuntimeResource runtimeResource;
-//			final Bundle bundle;
-//			if (transitive) {
-				// Transitive dependencies should be provisioned into the highest possible level.
-				// Transitive dependencies do not become a constituent.
-				// TODO Assumes root is always the appropriate level.
-//				AriesSubsystem subsystem = this;
-//				while (subsystem.parent != null)
-//					subsystem = subsystem.parent;
-				RuntimeResource runtimeResource = new RuntimeResourceFactoryImpl().create(resource, null, this);
-				runtimeResource.install(coordination);
-//				subsystem.constituents.add(runtimeResource);
-//				bundle = subsystem.region.installBundle(location, new URL(content).openStream());
-//			}
-//			else if (region == null) {
-				// Feature resources should be provisioned into the parent, unless the parent is also a feature.
-				// TODO Assumes parent is always highest possible level.
-//				AriesSubsystem subsystem = this.parent;
-//				while (subsystem.region == null)
-//					subsystem = subsystem.parent;
-//				runtimeResource = new RuntimeResourceFactoryImpl().create(resource, null, this);
-//				runtimeResource.install(coordination);
-//				bundle = subsystem.region.installBundle(location, new URL(content).openStream());
-				// Features retain their constituents.
-//				constituents.add(runtimeResource);
-//			}
-//			else {
-				// Constituent (non-transitive) resources must be provisioned into the owning subsystem, except for features.
-				// We know this isn't a feature because the region was not null.
-//				runtimeResource = new RuntimeResourceFactoryImpl().create(resource, null, this);
-//				runtimeResource.install(coordination);
-//				bundle = region.installBundle(location, new URL(content).openStream());
-//				constituents.add(runtimeResource);
-//			}
-//			coordination.addParticipant(new Participant() {
-//				public void ended(Coordination coordination) throws Exception {
-//					// noop
-//				}
-//	
-//				public void failed(Coordination coordination) throws Exception {
-//					constituents.remove(bundle.adapt(BundleRevision.class));
-//					region.removeBundle(bundle);
-//				}
-//			});
+	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;
 		}
-		catch (Exception e) {
-			throw new SubsystemException(e);
+		return constituentOf;
+	}
+	
+	private AriesSubsystem getProvisionTo(Resource resource, boolean transitive) {
+		// Application and composite resources are provisioned into the application or composite.
+		AriesSubsystem provisionTo = this;
+		if (transitive) {
+			// Transitive dependencies should be provisioned into the highest possible level.
+			// TODO Assumes root is always the appropriate level.
+			while (provisionTo.getParent() != null)
+				provisionTo = provisionTo.getParent();
+		}
+		else {
+			if (provisionTo.isFeature())
+				// Feature resources should be provisioned into the first parent that's not a feature.
+				while (provisionTo.region == null)
+					provisionTo = provisionTo.getParent();
 		}
+		return provisionTo;
 	}
 	
-	private synchronized void installAsync() throws Exception {
+	private synchronized void initialize(InputStream content) throws BundleException, IOException, URISyntaxException {
+		if (content == null)
+			content = new URL(location).openStream();
+		File rootDirectory = Activator.getBundleContext().getDataFile("");
+		File subsystemDirectory = new File(rootDirectory, "subsystem" + id + System.getProperty("file.separator"));
+		archive = new Archive(location, subsystemDirectory, content);
+		region = createRegion();
+		environment = new SubsystemEnvironment(this);
+		if (archive.getSubsystemManifest() == null) {
+			SubsystemUri uri = new SubsystemUri(location);
+			archive.setSubsystemManifest(SubsystemManifest.newInstance(uri.getSymbolicName(), uri.getVersion(), archive.getResources()));
+		}
+	}
+
+	private synchronized void install() throws Exception {
 		List<Resource> contentResources = new ArrayList<Resource>();
 		List<Resource> transitiveDependencies = new ArrayList<Resource>();
-//		// Get the resources included within the archive.
-//		contentResources.addAll(archive.getResources());
-//		// Create a subsystem repository from the contents of the subsystem archive.
-//		if (!contentResources.isEmpty()) {
-//			Document document = RepositoryDescriptorGenerator.generateRepositoryDescriptor("subsystem" + getSubsystemId(), contentResources);
-//			File file = new File(archive.getDirectory() + "/repository.xml");
-//			FileOutputStream fout = new FileOutputStream(file);
-//		    TransformerFactory.newInstance().newTransformer().transform(new DOMSource(document), new StreamResult(fout));
-//		    fout.close();
-//		    repository = new RepositoryFactory().newRepository(file.toURI().toURL());
-//		}
-//		contentResources.clear();
-		DeploymentManifest manifest = archive.getDeploymentManifest();
+		DeploymentManifest manifest = getDeploymentManifest();
 		DeployedContentHeader contentHeader = manifest.getDeployedContent();
 		for (DeployedContent content : contentHeader.getDeployedContents()) {
 			Collection<Capability> capabilities = environment.findProviders(
@@ -624,12 +673,6 @@ public class AriesSubsystem implements S
 				throw new SubsystemException("Subsystem content resource does not exist: " + content.getName() + ";version=" + content.getDeployedVersion());
 			Resource resource = capabilities.iterator().next().getResource();
 			contentResources.add(resource);
-			
-//			// Find the most appropriate resource based on subsystem type.
-//			Resource resource = findContentResource(content.getNamespace(), content.getName(), String.valueOf(content.getDeployedVersion()));
-//			if (resource == null)
-//				throw new SubsystemException("Subsystem content resource does not exist: " + content.getName() + ";version=" + content.getDeployedVersion());
-//			contentResources.add(resource);
 		}
 		ProvisionResourceHeader resourceHeader = manifest.getProvisionResource();
 		if (resourceHeader != null) {
@@ -640,12 +683,6 @@ public class AriesSubsystem implements S
 					throw new SubsystemException("Subsystem content resource does not exist: " + content.getName() + ";version=" + content.getDeployedVersion());
 				Resource resource = capabilities.iterator().next().getResource();
 				transitiveDependencies.add(resource);
-				
-//				// Find the most appropriate resource based on subsystem type.
-//				Resource resource = findContentResource(content.getNamespace(), content.getName(), String.valueOf(content.getDeployedVersion()));
-//				if (resource == null)
-//					throw new SubsystemException("Subsystem transitive dependency does not exist: " + content.getName() + ";version=" + content.getDeployedVersion());
-//				transitiveDependencies.add(resource);
 			}
 		}
 		// Install content resources and transitive dependencies.
@@ -654,11 +691,11 @@ public class AriesSubsystem implements S
 			try {
 				// Install the content resources.
 				for (Resource resource : contentResources) {
-					install(resource, coordination, false);
+					installResource(resource, coordination, false);
 				}
 				// Discover and install transitive dependencies.
 				for (Resource resource : transitiveDependencies) {
-					install(resource, coordination, true);
+					installResource(resource, coordination, true);
 				}
 			}
 			catch (Exception e) {
@@ -668,10 +705,88 @@ public class AriesSubsystem implements S
 				coordination.end();
 			}
 		}
-		setState(Subsystem.State.INSTALLED);
-		postEvent(this, SubsystemConstants.EventType.INSTALLED);
 	}
 	
+	private void installBundleResource(Resource resource, Coordination coordination, boolean transitive) throws BundleException, IOException {
+		AriesSubsystem provisionTo;
+		Bundle bundle;
+		synchronized (resourceToSubsystems) {
+			if (resource instanceof BundleRevision) {
+				resourceToSubsystems.get(resource).add(this);
+				return;
+			}
+			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);
+					}
+				}
+			}
+		});
+	}
+
+	private void installResource(Resource resource, Coordination coordination, boolean transitive) throws IOException, BundleException {
+		String type = ResourceHelper.getTypeAttribute(resource);
+		// TODO Add to constants.
+		if ("osgi.subsystem".equals(type))
+			installSubsystemResource(resource, coordination, transitive);
+		else if (ResourceConstants.IDENTITY_TYPE_BUNDLE.equals(type))
+			installBundleResource(resource, coordination, transitive);
+		else
+			throw new SubsystemException("Unsupported resource type: " + type);
+	}
+
+	private void installSubsystemResource(Resource resource, Coordination coordination, boolean transitive) throws IOException {
+		final AriesSubsystem subsystem;
+		synchronized (resourceToSubsystems) {
+			if (resource instanceof Subsystem) {
+				resourceToSubsystems.get(resource).add(this);
+				return;
+			}
+			URL content = environment.getContent(resource);
+			String location = id + '@' + getSymbolicName() + '@' + content;
+			subsystem = (AriesSubsystem)install(location, content.openStream());
+			Set<Subsystem> subsystems = new HashSet<Subsystem>();
+			subsystems.add(this);
+			resourceToSubsystems.put(subsystem, subsystems);
+		}
+		coordination.addParticipant(new Participant() {
+			public void ended(Coordination coordination) throws Exception {
+				// noop
+			}
+	
+			public void failed(Coordination coordination) throws Exception {
+				subsystem.uninstall();
+				synchronized (resourceToSubsystems) {
+					Set<Subsystem> subsystems = resourceToSubsystems.get(subsystem);
+					subsystems.remove(AriesSubsystem.this);
+					if (subsystems.isEmpty()) {
+						resourceToSubsystems.remove(subsystem);
+					}
+				}
+			}
+		});
+	}
+
 	private boolean isRoot() {
 		return ROOT_LOCATION.equals(getLocation());
 	}
@@ -696,7 +811,7 @@ public class AriesSubsystem implements S
 			// Applications have an implicit import policy equating to "import everything that I require", which is not the same as features.
 			// This must be computed from the application requirements and will be done using the Wires returned by the Resolver, when one is available.
 			region.connectRegion(
-					parent.getRegion(), 
+					parent.region, 
 					region.getRegionDigraph().createRegionFilterBuilder().allowAll(RegionFilter.VISIBLE_ALL_NAMESPACE).build());
 		}
 		else if (isComposite()) {
@@ -704,137 +819,101 @@ public class AriesSubsystem implements S
 			// Composites specify an explicit import policy in their subsystem and deployment manifests.
 		}
 	}
-	
-//	private void start(Resource resource, Coordination coordination) throws BundleException {
-//		if (!(resource instanceof BundleRevision)) {
-//			throw new SubsystemException("Unsupported resource type: " + resource);
-//		}
-//		final Bundle bundle = ((BundleRevision)resource).getBundle();
-//		// We don't want the bundles to autostart. Starting bundles must be under the control of the
-//		// subsystem in order to guarantee ordering.
-//		bundle.start(Bundle.START_TRANSIENT);
-//		coordination.addParticipant(new Participant() {
-//			public void ended(Coordination coordination) throws Exception {
-//				// noop
-//			}
-//
-//			public void failed(Coordination coordination) throws Exception {
-//				bundle.stop();
-//			}
-//		});
-//	}
-	
-	private void startAsync() {
-		// TODO Need to hold a lock here to guarantee that another start operation can't occur when the state goes to RESOLVED.
-		// Resolve the subsystem, if necessary.
-		if (getState() == State.RESOLVING) { // Otherwise, the state will be STARTING.
-			try {
-				setImportIsolationPolicy();
-				if (!Activator.getFrameworkWiring().resolveBundles(getBundles())) {
-					throw new Exception("Framework could not resolve the bundles");
-				}
-				setExportIsolationPolicy();
-				// TODO Could avoid calling setState (and notifyAll) here and avoid the need for a lock.
-				setState(State.RESOLVED);
-				postEvent(AriesSubsystem.this, SubsystemConstants.EventType.RESOLVED);
-				setState(State.STARTING);
-				postEvent(AriesSubsystem.this, SubsystemConstants.EventType.STARTING);
-			}
-			catch (Exception e) {
-				setState(State.INSTALLED);
-				postEvent(AriesSubsystem.this, SubsystemConstants.EventType.FAILED, e);
-				return;
-			}
-		}
-		// Start the subsystem.
-		Coordination coordination = Activator.getCoordinator().create(getSymbolicName() + '-' + getSubsystemId(), 0);
-		try {
-			for (Resource resource : constituents) {
-				((RuntimeResource)resource).start(coordination);
-			}
-		}
-		catch (Exception e) {
-			coordination.fail(e);
-			// TODO Need to reinstate complete isolation by disconnecting the region and transition to INSTALLED.
-		}
-		finally {
-			try {
-				coordination.end();
+
+	private void startBundleResource(Resource resource, Coordination coordination) throws BundleException {
+		final Bundle bundle = ((BundleRevision)resource).getBundle();
+		bundle.start(Bundle.START_TRANSIENT);
+		if (coordination == null)
+			return;
+		coordination.addParticipant(new Participant() {
+			public void ended(Coordination coordination) throws Exception {
+				// noop
 			}
-			catch (CoordinationException e) {
-				setState(State.RESOLVED);
-				postEvent(AriesSubsystem.this, SubsystemConstants.EventType.FAILED, e);
+	
+			public void failed(Coordination coordination) throws Exception {
+				bundle.stop();
 			}
-		}
-//		try {
-//			for (Resource resource : constituents) {
-//				start(resource, coordination);
-//			}
-//		}
-//		catch (Exception e) {
-//			coordination.fail(e);
-//			// TODO Need to reinstate complete isolation by disconnecting the region and transition to INSTALLED.
-//		}
-//		finally {
-//			try {
-//				coordination.end();
-//			}
-//			catch (CoordinationException e) {
-//				setState(State.RESOLVED);
-//				postEvent(AriesSubsystem.this, SubsystemConstants.EventType.FAILED, e);
-//			}
-//		}
-		setState(State.ACTIVE);
-		postEvent(AriesSubsystem.this, SubsystemConstants.EventType.STARTED);
-	}
-	
-	private void stop(Resource resource) throws Exception {
-		((RuntimeResource)resource).stop(null);
-//		if (!(resource instanceof BundleRevision)) {
-//			throw new SubsystemException("Unsupported resource type: " + resource);
-//		}
-//		final Bundle bundle = ((BundleRevision)resource).getBundle();
-//		bundle.stop();
+		});
 	}
+
+	private void startResource(Resource resource, Coordination coordination) throws BundleException {
+		String type = ResourceHelper.getTypeAttribute(resource);
+		// TODO Add to constants.
+		if ("osgi.subsystem".equals(type))
+			startSubsystemResource(resource, coordination);
+		else if (ResourceConstants.IDENTITY_TYPE_BUNDLE.equals(type))
+			startBundleResource(resource, coordination);
+		else
+			throw new SubsystemException("Unsupported resource type: " + type);
+	}
+
+	private void startSubsystemResource(Resource resource, Coordination coordination) {
+		final Subsystem subsystem = (Subsystem)resource;
+		subsystem.start();
+		if (coordination == null)
+			return;
+		coordination.addParticipant(new Participant() {
+			public void ended(Coordination coordination) throws Exception {
+				// noop
+			}
 	
-	private void stopAsync() {
-		// TODO Persist stop state.
-		for (Resource resource : constituents) {
-			try {
-				stop(resource);
+			public void failed(Coordination coordination) throws Exception {
+				subsystem.stop();
 			}
-			catch (Exception e) {
-				// TODO Should FAILED go out for each failure?
-				postEvent(AriesSubsystem.this, SubsystemConstants.EventType.FAILED, e);
+		});
+	}
+
+	private void stopBundleResource(Resource resource) throws BundleException {
+		((BundleRevision)resource).getBundle().stop();
+	}
+
+	private void stopResource(Resource resource) throws BundleException {
+		String type = ResourceHelper.getTypeAttribute(resource);
+		// TODO Add to constants.
+		if ("osgi.subsystem".equals(type))
+			stopSubsystemResource(resource);
+		else if (ResourceConstants.IDENTITY_TYPE_BUNDLE.equals(type))
+			stopBundleResource(resource);
+		else
+			throw new SubsystemException("Unsupported resource type: " + type);
+	}
+
+	private void stopSubsystemResource(Resource resource) {
+		((Subsystem)resource).stop();
+	}
+
+	private void uninstallBundleResource(Resource resource) throws BundleException {
+		synchronized (resourceToSubsystems) {
+			Set<Subsystem> subsystems = resourceToSubsystems.get(resource);
+			subsystems.remove(this);
+			if (!subsystems.isEmpty()) {
+				return;
 			}
+			subsystems.remove(resource);
 		}
-		// TODO Can we automatically assume it actually is resolved?
-		setState(State.RESOLVED);
-		postEvent(AriesSubsystem.this, SubsystemConstants.EventType.STOPPED);
+		((BundleRevision)resource).getBundle().uninstall();
 	}
-	
-	private void uninstall(Resource resource) throws Exception {
-		((RuntimeResource)resource).uninstall(null);
-//		if (!(resource instanceof BundleRevision)) {
-//			throw new SubsystemException("Unsupported resource type: " + resource);
-//		}
-//		final Bundle bundle = ((BundleRevision)resource).getBundle();
-//		bundle.uninstall();
+
+	private void uninstallResource(Resource resource) throws BundleException {
+		String type = ResourceHelper.getTypeAttribute(resource);
+		// TODO Add to constants.
+		if ("osgi.subsystem".equals(type))
+			uninstallSubsystemResource(resource);
+		else if (ResourceConstants.IDENTITY_TYPE_BUNDLE.equals(type))
+			uninstallBundleResource(resource);
+		else
+			throw new SubsystemException("Unsupported resource type: " + type);
 	}
-	
-	private void uninstallAsync() {
-		for (Resource resource : constituents) {
-			try {
-				uninstall(resource);
-			}
-			catch (Exception e) {
-				// TODO Should FAILED go out for each failure?
-				postEvent(AriesSubsystem.this, SubsystemConstants.EventType.FAILED, e);
+
+	private void uninstallSubsystemResource(Resource resource) {
+		synchronized (resourceToSubsystems) {
+			Set<Subsystem> subsystems = resourceToSubsystems.get(resource);
+			subsystems.remove(this);
+			if (!subsystems.isEmpty()) {
+				return;
 			}
+			subsystems.remove(resource);
 		}
-		parent.children.remove(this);
-		deleteFile(Activator.getBundleContext().getDataFile("subsystem" + id + System.getProperty("file.separator")));
-		setState(State.UNINSTALLED);
-		postEvent(AriesSubsystem.this, SubsystemConstants.EventType.UNINSTALLED);
+		((Subsystem)resource).uninstall();
 	}
 }

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleEventHandler.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleEventHandler.java?rev=1162585&r1=1162584&r2=1162585&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleEventHandler.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleEventHandler.java Sun Aug 28 20:39:09 2011
@@ -34,7 +34,7 @@ public class BundleEventHandler implemen
 		}
 		Bundle bundle = (Bundle)event.getProperty(EventConstants.BUNDLE);
 		Resource resource = bundle.adapt(BundleRevision.class);
-		Collection<AriesSubsystem> subsystems = Activator.getSubsystemManager().getSubsystems(resource);
+		Collection<AriesSubsystem> subsystems = AriesSubsystem.getSubsystems(resource);
 		for (AriesSubsystem subsystem : subsystems) {
 			Map<String, Object> map = new HashMap<String, Object>();
 			for (String propertyName : event.getPropertyNames()) {

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/OsgiIdentityCapability.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/OsgiIdentityCapability.java?rev=1162585&r1=1162584&r2=1162585&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/OsgiIdentityCapability.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/OsgiIdentityCapability.java Sun Aug 28 20:39:09 2011
@@ -16,8 +16,8 @@ package org.apache.aries.subsystem.core.
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.jar.Manifest;
 
+import org.apache.aries.subsystem.core.archive.BundleManifest;
 import org.apache.aries.subsystem.core.archive.SubsystemManifest;
 import org.osgi.framework.Constants;
 import org.osgi.framework.Version;
@@ -56,14 +56,15 @@ public class OsgiIdentityCapability impl
 				resource,
 				manifest.getSubsystemSymbolicName().getSymbolicName(),
 				manifest.getSubsystemVersion().getVersion(),
-				manifest.getSubsystemType().getValue());
+				// TODO Add to constants.
+				"osgi.subsystem");
 	}
 	
-	public OsgiIdentityCapability(Resource resource, Manifest manifest) {
+	public OsgiIdentityCapability(Resource resource, BundleManifest manifest) {
 		this(
 				resource,
-				manifest.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME),
-				Version.parseVersion(manifest.getMainAttributes().getValue(Constants.BUNDLE_VERSION)),
+				manifest.getHeader(Constants.BUNDLE_SYMBOLICNAME).getValue(),
+				Version.parseVersion(manifest.getHeader(Constants.BUNDLE_VERSION).getValue()),
 				ResourceConstants.IDENTITY_TYPE_BUNDLE);
 	}
 

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemBundleListener.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemBundleListener.java?rev=1162585&r1=1162584&r2=1162585&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemBundleListener.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemBundleListener.java Sun Aug 28 20:39:09 2011
@@ -19,8 +19,7 @@ import org.osgi.framework.wiring.BundleR
 
 public class SubsystemBundleListener implements BundleListener {
 	public void bundleChanged(BundleEvent event) {
-		SubsystemManager manager = Activator.getSubsystemManager();
-		for (AriesSubsystem subsystem : manager.getSubsystems(event.getBundle().adapt(BundleRevision.class))) {
+		for (AriesSubsystem subsystem : AriesSubsystem.getSubsystems(event.getBundle().adapt(BundleRevision.class))) {
 			// TODO Anything?
 		}
 	}

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=1162585&r1=1162584&r2=1162585&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 Sun Aug 28 20:39:09 2011
@@ -22,8 +22,12 @@ import org.osgi.framework.wiring.BundleR
 import org.osgi.framework.wiring.BundleRevision;
 import org.osgi.framework.wiring.Resource;
 import org.osgi.service.subsystem.Subsystem;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class SubsystemResolverHook implements ResolverHook {
+	private static final Logger LOGGER = LoggerFactory.getLogger(SubsystemResolverHook.class);
+	
 	public void end() {
 		// noop
 	}
@@ -33,22 +37,26 @@ public class SubsystemResolverHook imple
 	}
 
 	public void filterResolvable(Collection<BundleRevision> candidates) {
-		SubsystemManager manager = Activator.getSubsystemManager();
-		for (Resource candidate : candidates) {
-			Collection<AriesSubsystem> subsystems = manager.getSubsystems(candidate);
-			for (AriesSubsystem subsystem : subsystems) {
-				// TODO Uncomment when features are implemented.
-//				if (subsystem instanceof FeatureSubsystem) {
-//					// Feature subsystems require no isolation.
-//					continue;
-//				}
-				// Otherwise, the candidate is part of an application or composite subsystem requiring isolation.
-				// But only when in the INSTALLING or INSTALLED state.
-				if (EnumSet.of(Subsystem.State.INSTALLING, Subsystem.State.INSTALLED).contains(subsystem.getState())) {
-					candidates.remove(candidate);
+		try {
+			for (Resource candidate : candidates) {
+				Collection<AriesSubsystem> subsystems = AriesSubsystem.getSubsystems(candidate);
+				for (AriesSubsystem subsystem : subsystems) {
+					if (subsystem.isFeature()) {
+						// Feature subsystems require no isolation.
+						continue;
+					}
+					// Otherwise, the candidate is part of an application or composite subsystem requiring isolation.
+					// But only when in the INSTALLING or INSTALLED state.
+					if (EnumSet.of(Subsystem.State.INSTALLING, Subsystem.State.INSTALLED).contains(subsystem.getState())) {
+						candidates.remove(candidate);
+					}
 				}
 			}
 		}
+		catch (RuntimeException e) {
+			// This try/catch block is in place because exceptions occurring here are not showing up in the console during testing.
+			LOGGER.debug("Unexpected exception while filtering resolution candidates: " + candidates, e);
+		}
 	}
 
 	public void filterSingletonCollisions(BundleCapability singleton, Collection<BundleCapability> collisionCandidates) {

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=1162585&r1=1162584&r2=1162585&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 Sun Aug 28 20:39:09 2011
@@ -29,7 +29,7 @@ public class SubsystemSynchronousBundleL
 			return;
 		}
 		Resource resource = bundle.adapt(BundleRevision.class);
-		Collection<AriesSubsystem> subsystems = Activator.getSubsystemManager().getSubsystems(resource);
+		Collection<AriesSubsystem> subsystems = AriesSubsystem.getSubsystems(resource);
 		for (AriesSubsystem subsystem : subsystems) {
 			subsystem.bundleChanged(event);
 		}



Mime
View raw message