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/05/31 16:00:58 UTC

svn commit: r1344727 [1/2] - in /aries/trunk/subsystem: subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ subsystem-itests/src/test/java/org/apache/aries/subsyst...

Author: jwross
Date: Thu May 31 14:00:57 2012
New Revision: 1344727

URL: http://svn.apache.org/viewvc?rev=1344727&view=rev
Log:
ARIES-825: Multiple Changes

(1) Fixed issue in tests where an INSTALLED state change was expected during the uninstall process for a subsystem starting from the INSTALLED state.
(2) Refactored install and uninstall code. Broke functionality out into dedicated ResourceInstaller and ResourceUninstaller classes.
(3) Consolidated all primary data structures into dedicated Subsystems class.

Added:
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleResourceInstaller.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleResourceUninstaller.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResourceInstaller.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResourceUninstaller.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResourceInstaller.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResourceUninstaller.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Subsystems.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Utils.java
Modified:
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ProvisionResourceHeader.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemArchive.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/BundleEventHook.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/InstallAction.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Location.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/RawSubsystemResource.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/ResourceReferences.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/StartAction.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemGraph.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/SubsystemResource.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/ProvisionResourceHeader.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ProvisionResourceHeader.java?rev=1344727&r1=1344726&r2=1344727&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ProvisionResourceHeader.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ProvisionResourceHeader.java Thu May 31 14:00:57 2012
@@ -18,6 +18,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
+import org.apache.aries.subsystem.core.internal.ResourceHelper;
 import org.osgi.framework.Version;
 import org.osgi.resource.Resource;
 
@@ -76,6 +77,23 @@ public class ProvisionResourceHeader ext
 							typeAttribute == null ? TypeAttribute.DEFAULT_VALUE : typeAttribute.getType()));
 		}
 	}
+	
+	public boolean contains(Resource resource) {
+		return getProvisionedResource(resource) != null;
+	}
+	
+	public ProvisionedResource getProvisionedResource(Resource resource) {
+		String symbolicName = ResourceHelper.getSymbolicNameAttribute(resource);
+		Version version = ResourceHelper.getVersionAttribute(resource);
+		String type = ResourceHelper.getTypeAttribute(resource);
+		for (ProvisionedResource provisionedResource : provisionedResources) {
+			if (symbolicName.equals(provisionedResource.getName())
+					&& provisionedResource.getDeployedVersion().equals(version)
+					&& type.equals(provisionedResource.getNamespace()))
+				return provisionedResource;
+		}
+		return null;
+	}
 
 	public List<ProvisionedResource> getProvisionedResources() {
 		return Collections.unmodifiableList(provisionedResources);

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemArchive.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemArchive.java?rev=1344727&r1=1344726&r2=1344727&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemArchive.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemArchive.java Thu May 31 14:00:57 2012
@@ -31,8 +31,8 @@ public class SubsystemArchive implements
 	private DeploymentManifest deploymentManifest;
 	private SubsystemManifest subsystemManifest;
 	
-	public SubsystemArchive(SubsystemResource resource, File directory) throws IOException {
-		this.directory = directory;
+	public SubsystemArchive(SubsystemResource resource) throws IOException {
+		this.directory = resource.getDirectory();
 		resources = resource.getResources();
 		setSubsystemManifest(resource.getSubsystemManifest());
 		setDeploymentManifest(resource.getDeploymentManifest());

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=1344727&r1=1344726&r2=1344727&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 Thu May 31 14:00:57 2012
@@ -69,8 +69,8 @@ public class Activator implements Bundle
 	private volatile SubsystemServiceRegistrar registrar;
 	private volatile RegionDigraph regionDigraph;
 	private volatile Resolver resolver;
-	private AriesSubsystem root;
 	private ServiceTracker<?,?> serviceTracker;
+	private volatile Subsystems subsystems;
 	
 	private final Collection<ServiceRegistration<?>> registrations = new HashSet<ServiceRegistration<?>>();
 	private final Collection<Repository> repositories = Collections.synchronizedSet(new HashSet<Repository>());
@@ -95,6 +95,10 @@ public class Activator implements Bundle
 		return resolver;
 	}
 	
+	public Subsystems getSubsystems() {
+		return subsystems;
+	}
+	
 	public SubsystemServiceRegistrar getSubsystemServiceRegistrar() {
 		logger.debug(LOG_ENTRY, "getSubsystemServiceRegistrar");
 		SubsystemServiceRegistrar result = registrar;
@@ -103,7 +107,7 @@ public class Activator implements Bundle
 	}
 	
 	public Repository getSystemRepository() {
-		return new SystemRepository(root);
+		return new SystemRepository(subsystems.getRootSubsystem());
 	}
 
 	@Override
@@ -134,7 +138,7 @@ public class Activator implements Bundle
 		registrations.add(bundleContext.registerService(ResolverHookFactory.class, new SubsystemResolverHookFactory(), null));
 		registrar = new SubsystemServiceRegistrar(bundleContext);
 		try {
-			root = new AriesSubsystem();
+			subsystems = new Subsystems();
 		}
 		catch (SubsystemException e) {
 			throw e;
@@ -142,6 +146,7 @@ public class Activator implements Bundle
 		catch (Exception e) {
 			throw new SubsystemException(e);
 		}
+		AriesSubsystem root = subsystems.getRootSubsystem();
 		root.install();
 		root.start();
 	}
@@ -149,7 +154,7 @@ public class Activator implements Bundle
 	private void deactivate() {
 		if (!isActive() || hasRequiredServices())
 			return;
-		root.stop0();
+		subsystems.getRootSubsystem().stop0();
 		for (ServiceRegistration<?> registration : registrations) {
 			try {
 				registration.unregister();

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/AriesSubsystem.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/AriesSubsystem.java?rev=1344727&r1=1344726&r2=1344727&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 Thu May 31 14:00:57 2012
@@ -26,14 +26,12 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
+import java.util.EnumSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Map.Entry;
-import java.util.Set;
 
 import org.apache.aries.subsystem.core.archive.DeploymentManifest;
 import org.apache.aries.subsystem.core.archive.ExportPackageCapability;
@@ -54,6 +52,7 @@ import org.apache.aries.subsystem.core.a
 import org.apache.aries.subsystem.core.archive.SubsystemImportServiceRequirement;
 import org.apache.aries.subsystem.core.archive.SubsystemManifest;
 import org.apache.aries.subsystem.core.archive.SubsystemTypeHeader;
+import org.apache.aries.util.io.IOUtils;
 import org.eclipse.equinox.region.Region;
 import org.eclipse.equinox.region.RegionDigraph;
 import org.eclipse.equinox.region.RegionFilter;
@@ -70,8 +69,8 @@ import org.osgi.resource.Capability;
 import org.osgi.resource.Requirement;
 import org.osgi.resource.Resource;
 import org.osgi.service.coordinator.Coordination;
+import org.osgi.service.coordinator.CoordinationException;
 import org.osgi.service.coordinator.Participant;
-import org.osgi.service.repository.RepositoryContent;
 import org.osgi.service.resolver.ResolutionException;
 import org.osgi.service.subsystem.Subsystem;
 import org.osgi.service.subsystem.SubsystemConstants;
@@ -89,69 +88,15 @@ public class AriesSubsystem implements S
 	
 	private static final Logger LOGGER = LoggerFactory.getLogger(AriesSubsystem.class);
 	
-	static final Map<String, AriesSubsystem> locationToSubsystem = Collections.synchronizedMap(new HashMap<String, AriesSubsystem>());
-	static final ResourceReferences resourceReferences = new ResourceReferences();
-	private static final Map<Resource, Set<AriesSubsystem>> resourceToSubsystems = Collections.synchronizedMap(new HashMap<Resource, Set<AriesSubsystem>>());
-	
-	static synchronized Collection<AriesSubsystem> getSubsystems(Resource resource) {
-		// If the provided resource is null, all subsystems are desired.
-		if (resource == null)
-			return locationToSubsystem.values();
-		// Otherwise, only subsystems associated with the provided resource are
-		// desired.
-		Collection<AriesSubsystem> result = resourceToSubsystems.get(resource);
-		if (result == null)
-			return Collections.emptyList();
-		// TODO Does this need to be a copy? Unmodifiable?
-		return result;
-	}
-	
-	private static synchronized void addResourceToSubsystem(Resource resource, AriesSubsystem subsystem) {
-		Set<AriesSubsystem> subsystems = resourceToSubsystems.get(resource);
-		if (subsystems == null) {
-			// TODO The new HashSet needs to be guarded by a lock.
-			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 deleteFile(File file) {
-		LOGGER.debug(LOG_ENTRY, "deleteFile", file);
-		if (file.isDirectory()) {
-			deleteFiles(file.listFiles());
-		}
-		LOGGER.debug("Deleting file {}", file);
-		if (!file.delete())
-			LOGGER.warn("Unable to delete file {}", file);
-		LOGGER.debug(LOG_EXIT, "deleteFile");
-	}
-	
-	private static void deleteFiles(File[] files) {
-		for (File file : files) {
-			deleteFile(file);
-		}
-	}
+	final SubsystemResource resource;
+	boolean autostart;
 	
 	private final SubsystemArchive archive;
-	private final Set<Resource> constituents = Collections.synchronizedSet(new HashSet<Resource>());
 	private final File directory;
 	private final long id;
 	private final String location;
 	private final Region region;
-	final SubsystemResource resource;
-	private final SubsystemGraph subsystemGraph;
 	
-	boolean autostart;
 	private Subsystem.State state = State.INSTALLING;
 	 
 	public AriesSubsystem() throws Exception {
@@ -176,7 +121,6 @@ public class AriesSubsystem implements S
 			location = ROOT_LOCATION;
 		}
 		region = createRegion(null);
-		// TODO The creation of the subsystem manifest is in two places. See other constructor.
 		SubsystemManifest subsystemManifest = archive.getSubsystemManifest();
 		if (subsystemManifest == null) {
 			// This is the first time the root subsystem has been initialized in
@@ -202,8 +146,6 @@ public class AriesSubsystem implements S
 					.version(getVersion()).content(archive.getResources())
 					.build();
 		}
-		// The root subsystem establishes the subsystem graph;
-		subsystemGraph = new SubsystemGraph(this);
 		archive.setDeploymentManifest(new DeploymentManifest(
 				deploymentManifest, 
 				subsystemManifest, 
@@ -213,32 +155,17 @@ public class AriesSubsystem implements S
 				location,
 				true,
 				true));
-		// TODO Begin proof of concept.
-		// This is a proof of concept for initializing the relationships between the root subsystem and bundles
-		// that already existed in its region. Not sure this will be the final resting place. Plus, there are issues
-		// since this does not take into account the possibility of already existing bundles going away or new bundles
-		// being installed out of band while this initialization is taking place. Need a bundle event hook for that.
-		BundleContext context = Activator.getInstance().getBundleContext();
-		for (long id : region.getBundleIds()) {
-			BundleRevision br = context.getBundle(id).adapt(BundleRevision.class);
-			bundleInstalled(br);
-		}
-		// TODO End proof of concept.
 		resource = null;
 		LOGGER.debug(LOG_EXIT, "init");
 	}
 	
 	public AriesSubsystem(SubsystemResource resource, AriesSubsystem parent) {
 		this.resource = resource;
-		subsystemGraph = parent.subsystemGraph;
 		this.location = resource.getLocation();
-		id = SubsystemIdentifier.getNextId();
-		String directoryName = "subsystem" + id;
-		directory = new File(Activator.getInstance().getBundleContext().getDataFile(""), directoryName);
-		if (!directory.mkdir())
-			throw new SubsystemException("Unable to make directory for " + directory.getAbsolutePath());
+		id = resource.getId();
+		directory = resource.getDirectory();
 		try {
-			archive = new SubsystemArchive(resource, directory);
+			archive = new SubsystemArchive(resource);
 			SubsystemManifestValidator.validate(this, archive.getSubsystemManifest());
 			// Unscoped subsystems don't get their own region. They share the region with their scoped parent.
 			if (isUnscoped())
@@ -284,12 +211,12 @@ public class AriesSubsystem implements S
 
 	@Override
 	public Collection<Subsystem> getChildren() {
-		return subsystemGraph.getChildren(this);
+		return Activator.getInstance().getSubsystems().getChildren(this);
 	}
 
 	@Override
-	public synchronized Collection<Resource> getConstituents() {
-		return Collections.unmodifiableCollection(new ArrayList<Resource>(constituents));
+	public Collection<Resource> getConstituents() {
+		return Activator.getInstance().getSubsystems().getConstituents(this);
 	}
 
 	@Override
@@ -300,7 +227,7 @@ public class AriesSubsystem implements S
 
 	@Override
 	public Collection<Subsystem> getParents() {
-		return subsystemGraph.getParents(this);
+		return Activator.getInstance().getSubsystems().getParents(this);
 	}
 
 	@Override
@@ -353,7 +280,13 @@ public class AriesSubsystem implements S
 	@Override
 	// TODO Remove this synchronization when the 'location lock' has been implemented.
 	public synchronized Subsystem install(String location, InputStream content) throws SubsystemException {
-		return AccessController.doPrivileged(new InstallAction(location, content, this, AccessController.getContext()));
+		try {
+			return AccessController.doPrivileged(new InstallAction(location, content, this, AccessController.getContext()));
+		}
+		finally {
+			// This method must guarantee the content input stream was closed.
+			IOUtils.close(content);
+		}
 	}
 	
 	public boolean isApplication() {
@@ -432,33 +365,24 @@ public class AriesSubsystem implements S
 				// The root subsystem may not be uninstalled.
 				checkRoot();
 				State state = getState();
-				if (state == State.UNINSTALLING || state == State.UNINSTALLED || state == State.INSTALL_FAILED) {
+				// UNINSTALLING is included here because the transition to
+				// UNINSTALLED is guaranteed, so there's no point in waiting.
+				if (EnumSet.of(State.UNINSTALLING, State.UNINSTALLED).contains(state))
 					return null;
-				}
-				else if (state == State.INSTALLING || state == State.RESOLVING || state == State.STARTING || state == State.STOPPING) {
+				else if (EnumSet.of(State.INSTALLING, State.RESOLVING, State.STARTING, State.STOPPING).contains(state)) {
 					waitForStateChange();
 					uninstall();
 				}
-				else if (getState() == State.ACTIVE) {
+				else if (state.equals(State.ACTIVE)) {
 					stop();
 					uninstall();
 				}
-				uninstall(true);
+				ResourceUninstaller.newInstance(AriesSubsystem.this).uninstall();
 				return null;
 			}
 		});
 	}
 	
-	synchronized void bundleInstalled(BundleRevision revision) {
-		addResourceToSubsystem(revision, this);
-		constituents.add(revision);
-	}
-	
-	synchronized void bundleUninstalled(BundleRevision revision) {
-		constituents.remove(revision);
-		removeResourceToSubsystem(revision, this);
-	}
-	
 	AriesSubsystem findScopedSubsystemInRegion() {
 		AriesSubsystem result = this;
 		while (!result.isScoped())
@@ -466,6 +390,10 @@ public class AriesSubsystem implements S
 		return result;
 	}
 	
+	File getDirectory() {
+		return directory;
+	}
+	
 	Region getRegion() {
 		return region;
 	}
@@ -475,6 +403,17 @@ public class AriesSubsystem implements S
 				.getCoordinator()
 				.create(getSymbolicName() + "-" + getSubsystemId(), 0);
 		try {
+			// TODO Begin proof of concept.
+			// This is a proof of concept for initializing the relationships between the root subsystem and bundles
+			// that already existed in its region. Not sure this will be the final resting place. Plus, there are issues
+			// since this does not take into account the possibility of already existing bundles going away or new bundles
+			// being installed out of band while this initialization is taking place. Need a bundle event hook for that.
+			BundleContext context = Activator.getInstance().getBundleContext();
+			for (long id : region.getBundleIds()) {
+				BundleRevision br = context.getBundle(id).adapt(BundleRevision.class);
+				installResource(br, coordination, false);
+			}
+			// TODO End proof of concept.
 			install(coordination, null);
 		} catch (Exception e) {
 			coordination.fail(e);
@@ -483,6 +422,138 @@ public class AriesSubsystem implements S
 		}
 	}
 	
+	synchronized void install(Coordination coordination, AriesSubsystem parent) throws Exception {
+		if (!State.INSTALLING.equals(getState()))
+			return;
+		Activator.getInstance().getSubsystems().addSubsystem(this);
+		coordination.addParticipant(new Participant() {
+			@Override
+			public void ended(Coordination arg0) throws Exception {
+				// Nothing
+			}
+	
+			@Override
+			public void failed(Coordination arg0) throws Exception {
+				Activator.getInstance().getSubsystems().removeSubsystem(AriesSubsystem.this);
+			}
+		});
+		if (!isFeature())
+			RegionContextBundleHelper.installRegionContextBundle(this);
+		Activator.getInstance().getSubsystemServiceRegistrar().register(this, parent);
+		// Set up the sharing policy before installing the resources so that the
+		// environment can filter out capabilities from dependencies being
+		// provisioned to regions that are out of scope. This doesn't hurt
+		// anything since the resources are disabled from resolving anyway.
+		setImportIsolationPolicy();
+		// The subsystem resource will be null for the root subsystem.
+		if (this.resource != null) {
+			Comparator<Resource> comparator = new InstallResourceComparator();
+			// Install dependencies first...
+			List<Resource> dependencies = new ArrayList<Resource>(resource.getInstallableDependencies());
+			Collections.sort(dependencies, comparator);
+			for (Resource resource : dependencies)
+				installResource(resource, coordination, true);
+			// ...followed by content.
+			List<Resource> content = new ArrayList<Resource>(resource.getInstallableContent());
+			Collections.sort(content, comparator);
+			for (Resource resource : content)
+				installResource(resource, coordination, false);
+			// Simulate installation of shared content so that necessary relationships are established.
+			for (Resource resource : this.resource.getSharedContent())
+				installResource(resource, coordination, false);
+		}
+		setState(State.INSTALLED);
+		if (autostart)
+			start();
+	}
+
+	void installResource(Resource resource) {
+		Coordination coordination = Utils.createCoordination(this);
+		try {
+			installResource(resource, coordination, false);
+		}
+		catch (Throwable t) {
+			coordination.fail(t);
+		}
+		finally {
+			try {
+				coordination.end();
+			}
+			catch (CoordinationException e) {
+				Throwable t = e.getCause();
+				if (t instanceof SubsystemException)
+					throw (SubsystemException)t;
+				if (t instanceof SecurityException)
+					throw (SecurityException)t;
+				throw new SubsystemException(t);
+			}
+		}
+	}
+
+	void installResource(Resource resource, Coordination coordination, boolean transitive) throws Exception {
+		String type = ResourceHelper.getTypeAttribute(resource);
+		if (SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION.equals(type)
+				|| SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE.equals(type)
+				|| SubsystemConstants.SUBSYSTEM_TYPE_FEATURE.equals(type))
+			new SubsystemResourceInstaller(coordination, resource, this, transitive).install();
+		else if (IdentityNamespace.TYPE_BUNDLE.equals(type) ||
+				IdentityNamespace.TYPE_FRAGMENT.equals(type))
+			new BundleResourceInstaller(coordination, resource, this, transitive).install();
+		else
+			throw new SubsystemException("Unsupported resource type: " + type);
+	}
+
+	boolean isScoped() {
+		return isApplication() || isComposite();
+	}
+
+	void resolve() {
+		if (state != State.INSTALLED)
+			return;
+		setState(State.RESOLVING);
+		try {
+			for (Subsystem child : Activator.getInstance().getSubsystems().getChildren(this))
+				((AriesSubsystem)child).resolve();
+			// TODO I think this is insufficient. Do we need both
+			// pre-install and post-install environments for the Resolver?
+			Collection<Bundle> bundles = getBundles();
+			if (!Activator.getInstance().getBundleContext().getBundle(0)
+					.adapt(FrameworkWiring.class).resolveBundles(bundles)) {
+				LOGGER.error(
+						"Unable to resolve bundles for subsystem/version/id {}/{}/{}: {}",
+						new Object[] { getSymbolicName(), getVersion(),
+								getSubsystemId(), bundles });
+				// TODO SubsystemException?
+				throw new SubsystemException("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);
+		}
+		catch (Throwable t) {
+			setState(State.INSTALLED);
+			if (t instanceof SubsystemException)
+				throw (SubsystemException)t;
+			throw new SubsystemException(t);
+		}
+	}
+
+	void startResource(Resource resource, Coordination coordination) throws BundleException, IOException {
+		String type = ResourceHelper.getTypeAttribute(resource);
+		if (SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION.equals(type)
+				|| SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE.equals(type)
+				|| SubsystemConstants.SUBSYSTEM_TYPE_FEATURE.equals(type))
+			startSubsystemResource(resource, coordination);
+		else if (IdentityNamespace.TYPE_BUNDLE.equals(type))
+			startBundleResource(resource, coordination);
+		else if (IdentityNamespace.TYPE_FRAGMENT.equals(type)) {
+			// Fragments are not started.
+		}
+		else
+			throw new SubsystemException("Unsupported resource type: " + type);
+	}
+
 	void stop0() {
 		if (getState() == State.UNINSTALLING || getState() == State.UNINSTALLED) {
 			throw new SubsystemException("Cannot stop from state " + getState());
@@ -497,7 +568,7 @@ public class AriesSubsystem implements S
 		setState(State.STOPPING);
 		// For non-root subsystems, stop any remaining constituents.
 		if (!isRoot()){
-			List<Resource> resources = new ArrayList<Resource>(resourceReferences.getResources(this));
+			List<Resource> resources = new ArrayList<Resource>(Activator.getInstance().getSubsystems().getResourcesReferencedBy(this));
 			if (resource != null) {
 				Collections.sort(resources, new StartResourceComparator(resource.getSubsystemManifest().getSubsystemContentHeader()));
 				Collections.reverse(resources);
@@ -534,11 +605,21 @@ public class AriesSubsystem implements S
 		}
 	}
 	
+	synchronized void waitForStateChange() {
+		try {
+			wait();
+		}
+		catch (InterruptedException e) {
+			throw new SubsystemException(e);
+		}
+	}
+	
 	protected boolean contains(Resource resource) {
-		return constituents.contains(resource);
+		return Activator.getInstance().getSubsystems().getConstituents(this).contains(resource);
 	}
 	
 	protected Collection<Bundle> getBundles() {
+		Collection<Resource> constituents = Activator.getInstance().getSubsystems().getConstituents(this);
 		ArrayList<Bundle> result = new ArrayList<Bundle>(constituents.size());
 		for (Resource resource : constituents) {
 			if (resource instanceof BundleRevision)
@@ -554,15 +635,6 @@ public class AriesSubsystem implements S
 		notifyAll();
 	}
 	
-	synchronized void waitForStateChange() {
-		try {
-			wait();
-		}
-		catch (InterruptedException e) {
-			throw new SubsystemException(e);
-		}
-	}
-	
 	private void addSubsystemServiceImportToSharingPolicy(
 			RegionFilterBuilder builder) throws InvalidSyntaxException {
 		builder.allow(
@@ -623,198 +695,14 @@ public class AriesSubsystem implements S
 		return archive.getDeploymentManifest();
 	}
 	
-	private synchronized void install(Coordination coordination, AriesSubsystem parent) throws Exception {
-		if (!State.INSTALLING.equals(getState()))
-			return;
-		if (!isFeature())
-			RegionContextBundleHelper.installRegionContextBundle(this);
-		Activator.getInstance().getSubsystemServiceRegistrar().register(this, parent);
-		// Set up the sharing policy before installing the resources so that the
-		// environment can filter out capabilities from dependencies being
-		// provisioned to regions that are out of scope. This doesn't hurt
-		// anything since the resources are disabled from resolving anyway.
-		setImportIsolationPolicy();
-		// The subsystem resource will be null for the root subsystem.
-		if (this.resource != null) {
-			Comparator<Resource> comparator = new InstallResourceComparator();
-			// Install dependencies first...
-			List<Resource> dependencies = new ArrayList<Resource>(resource.getInstallableDependencies());
-			Collections.sort(dependencies, comparator);
-			for (Resource resource : dependencies)
-				installResource(resource, coordination, true);
-			// ...followed by content.
-			List<Resource> content = new ArrayList<Resource>(resource.getInstallableContent());
-			Collections.sort(content, comparator);
-			for (Resource resource : content)
-				installResource(resource, coordination, false);
-			// Simulate installation of shared content so that necessary relationships are established.
-			for (Resource resource : this.resource.getSharedContent())
-				installResource(resource, coordination, false);
-		}
-		setState(State.INSTALLED);
-		if (autostart)
-			start();
-	}
-
-	private Resource installBundleResource(Resource resource,
-			Coordination coordination, boolean transitive)
-			throws BundleException, IOException {
-		final BundleRevision revision;
-		if (resource instanceof BundleRevision) {
-			// This means the resource is an already installed bundle.
-			revision = (BundleRevision) resource;
-			// Transitive runtime resources need no further processing here.
-			if (!transitive) {
-				// Need to simulate the install process since an install does
-				// not actually occur here, and the event hook is not called.
-				bundleInstalled(revision);
-			}
-			return revision;
-		}
-		InputStream content = ((RepositoryContent) resource).getContent();
-		// By default, the resource is provisioned into this subsystem.
-		AriesSubsystem provisionTo = this;
-		if (transitive) {
-			// But transitive dependencies should be provisioned into the
-			// first subsystem that accepts dependencies.
-			while (provisionTo.archive.getSubsystemManifest()
-					.getSubsystemTypeHeader().getProvisionPolicyDirective()
-					.isRejectDependencies()) {
-				provisionTo = (AriesSubsystem) provisionTo.getParents()
-						.iterator().next();
-			}
-		}
-		String location = provisionTo.getSubsystemId() + "@"
-				+ provisionTo.getSymbolicName() + "@"
-				+ ResourceHelper.getSymbolicNameAttribute(resource);
-		ThreadLocalSubsystem.set(provisionTo);
-		Bundle bundle = provisionTo.region.installBundle(location, content);
-		revision = bundle.adapt(BundleRevision.class);
-		// Only need to add a participant when this subsystem is the actual
-		// installer of the bundle.
-		coordination.addParticipant(new Participant() {
-			public void ended(Coordination coordination) throws Exception {
-				// noop
-			}
-
-			public void failed(Coordination coordination) throws Exception {
-				revision.getBundle().uninstall();
-			}
-		});
-		return revision;
-	}
-
-	void installResource(Resource resource, Coordination coordination, boolean transitive) throws Exception {
-		final Resource installed;
-		String type = ResourceHelper.getTypeAttribute(resource);
-		if (SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION.equals(type)
-				|| SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE.equals(type)
-				|| SubsystemConstants.SUBSYSTEM_TYPE_FEATURE.equals(type))
-			installed = installSubsystemResource(resource, coordination, transitive);
-		else if (IdentityNamespace.TYPE_BUNDLE.equals(type) ||
-				IdentityNamespace.TYPE_FRAGMENT.equals(type))
-			installed = installBundleResource(resource, coordination, transitive);
-		else
-			throw new SubsystemException("Unsupported resource type: " + type);
-		resourceReferences.addReference(this, installed);
-		coordination.addParticipant(new Participant() {
-			@Override
-			public void ended(Coordination coordination) throws Exception {
-				// noop
-			}
-
-			@Override
-			public void failed(Coordination coordination) throws Exception {
-				resourceReferences.removeReference(AriesSubsystem.this, installed);
-			}
-		});
-	}
-
-	private Resource installSubsystemResource(Resource resource, Coordination coordination, boolean transitive) throws Exception {
-		final AriesSubsystem subsystem;
-		if (resource instanceof RepositoryContent) {
-			String location = getSubsystemId() + "@" + getSymbolicName() + "@" + ResourceHelper.getSymbolicNameAttribute(resource);
-			InputStream content = ((RepositoryContent)resource).getContent();
-			return AccessController.doPrivileged(new InstallAction(location, content, this, null, coordination, true));
-		}
-		else if (resource instanceof AriesSubsystem) {
-			subsystem = (AriesSubsystem)resource;
-		}
-		else if (resource instanceof RawSubsystemResource) {
-			subsystem = new AriesSubsystem(new SubsystemResource((RawSubsystemResource)resource, this), this);
-		}
-		else if (resource instanceof SubsystemResource) {
-			subsystem = new AriesSubsystem((SubsystemResource)resource, this);
-		}
-		else {
-			throw new IllegalArgumentException("Unrecognized subsystem resource: " + resource);
-		}
-		// Detect a cycle before becoming a participant; otherwise, install failure cleanup goes awry
-		// because the parent in the cycle (i.e. the subsystem attempting to install here) is cleaned up 
-		// before the child. This results in the child (i.e. this subsystem) being uninstalled as part
-		// of that process, but its state has not moved from INSTALLING to INSTALL_FAILED, which results
-		// in an eternal wait for a state change.
-		subsystemInstalling(subsystem);
-		coordination.addParticipant(new Participant() {
-			public void ended(Coordination coordination) throws Exception {
-				// noop
-			}
-	
-			public void failed(Coordination coordination) throws Exception {
-				subsystem.setState(State.INSTALL_FAILED);
-				subsystem.uninstall(false);
-				subsystemUninstalled(subsystem);
-			}
-		});
-		subsystem.install(coordination, this);
-		subsystemInstalled(subsystem);
-		return subsystem;
-	}
-
 	private boolean isRoot() {
 		return ROOT_LOCATION.equals(getLocation());
 	}
 	
-	private boolean isScoped() {
-		return isApplication() || isComposite();
-	}
-	
 	private boolean isUnscoped() {
 		return !isScoped();
 	}
 	
-	void resolve() {
-		if (state != State.INSTALLED)
-			return;
-		setState(State.RESOLVING);
-		try {
-			for (Subsystem child : subsystemGraph.getChildren(this))
-				((AriesSubsystem)child).resolve();
-			// TODO I think this is insufficient. Do we need both
-			// pre-install and post-install environments for the Resolver?
-			Collection<Bundle> bundles = getBundles();
-			if (!Activator.getInstance().getBundleContext().getBundle(0)
-					.adapt(FrameworkWiring.class).resolveBundles(bundles)) {
-				LOGGER.error(
-						"Unable to resolve bundles for subsystem/version/id {}/{}/{}: {}",
-						new Object[] { getSymbolicName(), getVersion(),
-								getSubsystemId(), bundles });
-				// TODO SubsystemException?
-				throw new SubsystemException("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);
-		}
-		catch (Throwable t) {
-			setState(State.INSTALLED);
-			if (t instanceof SubsystemException)
-				throw (SubsystemException)t;
-			throw new SubsystemException(t);
-		}
-	}
-	
 	private void setExportIsolationPolicy() throws InvalidSyntaxException, IOException, BundleException, URISyntaxException, ResolutionException {
 		if (isRoot())
 			// Nothing to do if this is the root subsystem.
@@ -990,21 +878,6 @@ public class AriesSubsystem implements S
 		});
 	}
 
-	void startResource(Resource resource, Coordination coordination) throws BundleException, IOException {
-		String type = ResourceHelper.getTypeAttribute(resource);
-		if (SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION.equals(type)
-				|| SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE.equals(type)
-				|| SubsystemConstants.SUBSYSTEM_TYPE_FEATURE.equals(type))
-			startSubsystemResource(resource, coordination);
-		else if (IdentityNamespace.TYPE_BUNDLE.equals(type))
-			startBundleResource(resource, coordination);
-		else if (IdentityNamespace.TYPE_FRAGMENT.equals(type)) {
-			// Fragments are not started.
-		}
-		else
-			throw new SubsystemException("Unsupported resource type: " + type);
-	}
-
 	private void startSubsystemResource(Resource resource, Coordination coordination) throws IOException {
 		final AriesSubsystem subsystem = (AriesSubsystem)resource;
 		subsystem.start();
@@ -1042,106 +915,4 @@ public class AriesSubsystem implements S
 	private void stopSubsystemResource(Resource resource) throws IOException {
 		((AriesSubsystem)resource).stop();
 	}
-	
-	synchronized void subsystemInstalled(AriesSubsystem subsystem) {
-		Activator.getInstance().getSubsystemServiceRegistrar().addRegion(subsystem, region);
-	}
-	
-	synchronized void subsystemInstalling(AriesSubsystem subsystem) {
-		locationToSubsystem.put(subsystem.getLocation(), subsystem);
-		subsystemGraph.add(this, subsystem);
-		addResourceToSubsystem(subsystem, this);
-		constituents.add(subsystem);
-	}
-	
-	private synchronized void subsystemUninstalled(AriesSubsystem subsystem) {
-		Activator.getInstance().getSubsystemServiceRegistrar().removeRegion(subsystem, region);
-		constituents.remove(subsystem);
-		removeResourceToSubsystem(subsystem, this);
-		subsystemGraph.remove(subsystem);
-		locationToSubsystem.remove(subsystem.getLocation());
-	}
-	
-	private void uninstall(boolean changeState) {
-		if (changeState)
-			setState(State.INSTALLED);
-		setState(State.UNINSTALLING);
-		// Uninstall child subsystems first.
-		for (Subsystem subsystem : getChildren()) {
-			try {
-				uninstallSubsystemResource((AriesSubsystem)subsystem);
-			}
-			catch (Exception e) {
-				LOGGER.error("An error occurred while uninstalling resource " + subsystem + " of subsystem " + this, e);
-				// TODO Should FAILED go out for each failure?
-			}
-		}
-		// Uninstall any remaining constituents.
-		for (Resource resource : resourceReferences.getResources(this)) {
-			// Don't uninstall a resource that is still referenced by other subsystems.
-			if (resourceReferences.getSubsystems(resource).size() > 1)
-				continue;
-			// Don't uninstall the region context bundle here.
-			if (ResourceHelper.getSymbolicNameAttribute(resource).startsWith(RegionContextBundleHelper.SYMBOLICNAME_PREFIX))
-				continue;
-			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?
-			}
-		}
-		for (Subsystem parent : getParents()) {
-			((AriesSubsystem)parent).constituents.remove(this);
-		}
-		subsystemGraph.remove(this);
-		locationToSubsystem.remove(location);
-		deleteFile(directory);
-		setState(State.UNINSTALLED);
-		Activator.getInstance().getSubsystemServiceRegistrar().unregister(this);
-		if (!isFeature())
-			RegionContextBundleHelper.uninstallRegionContextBundle(this);
-	}
-
-	private void uninstallBundleResource(Resource resource) throws BundleException {
-		LOGGER.debug(LOG_ENTRY, "uninstallBundleResource", resource);
-		BundleRevision revision = (BundleRevision)resource;
-		if (getSubsystems(revision).size() > 1) {
-			bundleUninstalled(revision);
-			return;
-		}
-		Bundle bundle = revision.getBundle();
-		LOGGER.debug("Uninstalling bundle {}", bundle);
-		bundle.uninstall();
-		LOGGER.debug(LOG_EXIT, "uninstallBundleResource");
-	}
-
-	private void uninstallResource(Resource resource) throws BundleException {
-		if (LOGGER.isDebugEnabled()) {
-			LOGGER.debug(LOG_ENTRY, "uninstallResource", resource);
-			LOGGER.debug("Subsystem {} is uninstalling resource {};{};{}", new Object[]{
-					getSymbolicName(),
-					ResourceHelper.getSymbolicNameAttribute(resource),
-					ResourceHelper.getVersionAttribute(resource),
-					ResourceHelper.getTypeAttribute(resource)
-			});
-		}
-		resourceReferences.removeReference(this, resource);
-		String type = ResourceHelper.getTypeAttribute(resource);
-		if (SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION.equals(type)
-				|| SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE.equals(type)
-				|| SubsystemConstants.SUBSYSTEM_TYPE_FEATURE.equals(type))
-			uninstallSubsystemResource(resource);
-		else if (IdentityNamespace.TYPE_BUNDLE.equals(type) || IdentityNamespace.TYPE_FRAGMENT.equals(type))
-			uninstallBundleResource(resource);
-		else
-			throw new SubsystemException("Unsupported resource type: " + type);
-		LOGGER.debug(LOG_EXIT, "uninstallResource");
-	}
-
-	private void uninstallSubsystemResource(Resource resource) {
-		removeResourceToSubsystem(resource, this);
-		((AriesSubsystem)resource).uninstall();
-	}
 }

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleEventHook.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleEventHook.java?rev=1344727&r1=1344726&r2=1344727&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleEventHook.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleEventHook.java Thu May 31 14:00:57 2012
@@ -34,49 +34,30 @@ public class BundleEventHook implements 
 		}
 	}
 	
-	private boolean handleExplicitlyInstalledBundleBundleContext(BundleRevision originRevision, BundleRevision bundleRevision) {
-		// This means that some other bundle's context was used. The bundle
-		// needs to be associated with all subsystems that are associated with
-		// the bundle whose context was used to install the bundle.
-		Collection<AriesSubsystem> subsystems = AriesSubsystem.getSubsystems(originRevision);
+	private void handleExplicitlyInstalledBundleBundleContext(BundleRevision originRevision, BundleRevision bundleRevision) {
+		// The bundle needs to be associated with all subsystems that are 
+		// associated with the bundle whose context was used to install the 
+		// bundle.
+		Collection<AriesSubsystem> subsystems = Activator.getInstance().getSubsystems().getSubsystemsReferencing(originRevision);
 		if (subsystems.isEmpty())
 			throw new IllegalStateException("Orphaned bundle revision detected: " + originRevision);
 		for (AriesSubsystem s : subsystems)
-			s.bundleInstalled(bundleRevision);
-		return true;
+			s.installResource(bundleRevision);
 	}
 	
-	private boolean handleExplicitlyInstalledBundleRegionDigraph(Bundle origin, BundleRevision bundleRevision) {
-		// Otherwise, this is an explicitly installed bundle. That is, the
-		// bundle is being installed outside of the Subsystem API using Region
-		// Digraph or some other bundle's context.
-		if ("org.eclipse.equionox.region".equals(origin.getSymbolicName())) {
-			// This means Region Digraph was used to install the bundle. The
-			// bundle needs to be associated with the scoped subsystem of the
-			// region used to install the bundle.
+	private void handleExplicitlyInstalledBundleRegionDigraph(Bundle origin, BundleRevision bundleRevision) {
+			// The bundle needs to be associated with the scoped subsystem of 
+			// the region used to install the bundle.
 			RegionDigraph digraph = Activator.getInstance().getRegionDigraph();
 			Region region = digraph.getRegion(origin);
-			for (AriesSubsystem s : AriesSubsystem.getSubsystems(null)) {
+			for (AriesSubsystem s : Activator.getInstance().getSubsystems().getSubsystems()) {
 				if ((s.isApplication() || s.isComposite())
 						&& region.equals(s.getRegion())) {
-					s.bundleInstalled(bundleRevision);
-					return true;
+					s.installResource(bundleRevision);
+					return;
 				}
 			}
 			throw new IllegalStateException("No subsystem found for bundle " + bundleRevision + " in region " + region);
-		}
-		return false;
-	}
-	
-	private boolean handleImplicitlyInstalledResource(BundleRevision bundleRevision) {
-		// If the thread local variable is set, this is an implicitly installed
-		// bundle and needs to be associated with the subsystem installing it.
-		AriesSubsystem subsystem = ThreadLocalSubsystem.get();
-		if (subsystem != null) {
-			subsystem.bundleInstalled(bundleRevision);
-			return true;
-		}
-		return false;
 	}
 	
 	private void handleInstalledEvent(BundleEvent event) {
@@ -84,21 +65,26 @@ public class BundleEventHook implements 
 		BundleRevision originRevision = origin.adapt(BundleRevision.class);
 		Bundle bundle = event.getBundle();
 		BundleRevision bundleRevision = bundle.adapt(BundleRevision.class);
-		if (!handleImplicitlyInstalledResource(bundleRevision)) {
-			if (!handleExplicitlyInstalledBundleRegionDigraph(origin, bundleRevision)) {
-				handleExplicitlyInstalledBundleBundleContext(originRevision, bundleRevision);
-			}
-		}
 		bundleToRevision.put(bundle, bundleRevision);
+		// Only handle explicitly installed bundles. An explicitly installed
+		// bundle is a bundle that was installed using some other bundle's
+		// BundleContext or using RegionDigraph.
+		if (ThreadLocalSubsystem.get() != null)
+			return;
+		if ("org.eclipse.equionox.region".equals(origin.getSymbolicName()))
+			// The bundle was installed using RegionDigraph.
+			handleExplicitlyInstalledBundleRegionDigraph(origin, bundleRevision);
+		else
+			// The bundle was installed using some other bundle's BundleContext.
+			handleExplicitlyInstalledBundleBundleContext(originRevision, bundleRevision);
 	}
 	
 	private void handleUninstalledEvent(BundleEvent event) {
 		Bundle bundle = event.getBundle();
 		BundleRevision revision = bundleToRevision.remove(bundle);
-		Collection<AriesSubsystem> subsystems = AriesSubsystem.getSubsystems(revision);
-		if (subsystems.isEmpty())
-			throw new IllegalStateException("Orphaned bundle revision detected: " + revision);
-		for (AriesSubsystem subsystem : subsystems)
-			subsystem.bundleUninstalled(revision);
+		if (ThreadLocalSubsystem.get() != null)
+			return;
+		for (AriesSubsystem subsystem : Activator.getInstance().getSubsystems().getSubsystemsByConstituent(revision))
+			ResourceUninstaller.newInstance(revision, subsystem).uninstall();
 	}
 }

Added: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleResourceInstaller.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleResourceInstaller.java?rev=1344727&view=auto
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleResourceInstaller.java (added)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleResourceInstaller.java Thu May 31 14:00:57 2012
@@ -0,0 +1,48 @@
+package org.apache.aries.subsystem.core.internal;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.resource.Resource;
+import org.osgi.service.coordinator.Coordination;
+import org.osgi.service.coordinator.Participant;
+import org.osgi.service.repository.RepositoryContent;
+import org.osgi.service.subsystem.SubsystemException;
+
+public class BundleResourceInstaller extends ResourceInstaller {
+	public BundleResourceInstaller(Coordination coordination, Resource resource, AriesSubsystem subsystem, boolean transitive) {
+		super(coordination, resource, subsystem, transitive);
+	}
+	
+	public void install() {
+		BundleRevision revision;
+		if (resource instanceof BundleRevision)
+			revision = (BundleRevision)resource;
+		else {
+			ThreadLocalSubsystem.set(provisionTo);
+			revision = installBundle();
+		}
+		addConstituent(revision);
+		addReference(revision);
+	}
+	
+	private BundleRevision installBundle() {
+		final Bundle bundle;
+		try {
+			bundle = provisionTo.getRegion().installBundle(getLocation(), ((RepositoryContent)resource).getContent());
+		}
+		catch (BundleException e) {
+			throw new SubsystemException(e);
+		}
+		coordination.addParticipant(new Participant() {
+			public void ended(Coordination coordination) throws Exception {
+				// Nothing
+			}
+
+			public void failed(Coordination coordination) throws Exception {
+				provisionTo.getRegion().removeBundle(bundle);
+			}
+		});
+		return bundle.adapt(BundleRevision.class);
+	}
+}

Added: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleResourceUninstaller.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleResourceUninstaller.java?rev=1344727&view=auto
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleResourceUninstaller.java (added)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleResourceUninstaller.java Thu May 31 14:00:57 2012
@@ -0,0 +1,44 @@
+package org.apache.aries.subsystem.core.internal;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.resource.Resource;
+import org.osgi.service.subsystem.SubsystemException;
+
+public class BundleResourceUninstaller extends ResourceUninstaller {
+	public BundleResourceUninstaller(Resource resource, AriesSubsystem subsystem) {
+		super(resource, subsystem);
+	}
+	
+	public void uninstall() {
+		if (!isResourceUninstallable())
+			return;
+		if (isBundleUninstallable())
+			uninstallBundle();
+		removeReference();
+		removeConstituent();
+	}
+	
+	private Bundle getBundle() {
+		return getBundleRevision().getBundle();
+	}
+	
+	private BundleRevision getBundleRevision() {
+		return (BundleRevision)resource;
+	}
+	
+	private boolean isBundleUninstallable() {
+		return getBundle().getState() != Bundle.UNINSTALLED;
+	}
+	
+	private void uninstallBundle() {
+		ThreadLocalSubsystem.set(provisionTo);
+		try {
+			getBundle().uninstall();
+		}
+		catch (BundleException e) {
+			throw new SubsystemException(e);
+		}
+	}
+}

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/InstallAction.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/InstallAction.java?rev=1344727&r1=1344726&r2=1344727&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/InstallAction.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/InstallAction.java Thu May 31 14:00:57 2012
@@ -5,8 +5,10 @@ import java.security.AccessControlContex
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 
+import org.apache.aries.util.io.IOUtils;
 import org.osgi.service.coordinator.Coordination;
 import org.osgi.service.coordinator.CoordinationException;
+import org.osgi.service.coordinator.Participant;
 import org.osgi.service.subsystem.SubsystemException;
 
 public class InstallAction implements PrivilegedAction<AriesSubsystem> {
@@ -38,8 +40,19 @@ public class InstallAction implements Pr
 			coordination = Activator.getInstance().getCoordinator().create(parent.getSymbolicName() + '-' + parent.getSubsystemId(), 0);
 		try {
 			TargetRegion region = new TargetRegion(parent);
-			SubsystemResource ssr = new SubsystemResource(location, content, parent);
-			result = AriesSubsystem.locationToSubsystem.get(location);
+			final SubsystemResource ssr = new SubsystemResource(location, content, parent);
+			coordination.addParticipant(new Participant() {
+				@Override
+				public void ended(Coordination c) throws Exception {
+					// Nothing
+				}
+
+				@Override
+				public void failed(Coordination c) throws Exception {
+					IOUtils.deleteRecursive(ssr.getDirectory());
+				}
+			});
+			result = Activator.getInstance().getSubsystems().getSubsystemByLocation(location);
 			if (result != null) {
 				checkLifecyclePermission(result);
 				if (!region.contains(result))
@@ -48,8 +61,7 @@ public class InstallAction implements Pr
 						&& result.getVersion().equals(ssr.getSubsystemManifest().getSubsystemVersionHeader().getVersion())
 						&& result.getType().equals(ssr.getSubsystemManifest().getSubsystemTypeHeader().getType())))
 					throw new SubsystemException("Location already exists but symbolic name, version, and type are not the same: " + location);
-				parent.subsystemInstalling(result);
-				parent.subsystemInstalled(result);
+				parent.installResource(result);
 				return result;
 			}
 			result = (AriesSubsystem)region.find(
@@ -59,8 +71,7 @@ public class InstallAction implements Pr
 				checkLifecyclePermission(result);
 				if (!result.getType().equals(ssr.getSubsystemManifest().getSubsystemTypeHeader().getType()))
 					throw new SubsystemException("Subsystem already exists in target region but has a different type: " + location);
-				parent.subsystemInstalling(result);
-				parent.subsystemInstalled(result);
+				parent.installResource(result);
 				return result;
 			}
 			result = new AriesSubsystem(ssr, parent);

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Location.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Location.java?rev=1344727&r1=1344726&r2=1344727&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Location.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Location.java Thu May 31 14:00:57 2012
@@ -9,23 +9,19 @@ import java.net.URL;
 import org.osgi.framework.Version;
 
 public class Location {
-	private final String symbolicName;
-	private final URL url;
+	private final SubsystemUri uri;
 	private final String value;
-	private final Version version;
 	
 	public Location(String location) throws MalformedURLException, URISyntaxException {
 		value = location;
-		SubsystemUri uri = null;
 		if (location.startsWith("subsystem://"))
 			uri = new SubsystemUri(location);
-		symbolicName = uri == null ? null : uri.getSymbolicName();
-		url = uri == null ? null : uri.getURL();
-		version = uri == null ? null : uri.getVersion();
+		else
+			uri = null;
 	}
 	
 	public String getSymbolicName() {
-		return symbolicName;
+		return uri == null ? null : uri.getSymbolicName();
 	}
 	
 	public String getValue() {
@@ -33,10 +29,10 @@ public class Location {
 	}
 	
 	public Version getVersion() {
-		return version;
+		return uri == null ? null : uri.getVersion();
 	}
 	
 	public InputStream open() throws IOException {
-		return url == null ? new URL(value).openStream() : url.openStream();
+		return uri == null ? new URL(value).openStream() : uri.getURL().openStream();
 	}
 }
\ No newline at end of file

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/RawSubsystemResource.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/RawSubsystemResource.java?rev=1344727&r1=1344726&r2=1344727&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/RawSubsystemResource.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/RawSubsystemResource.java Thu May 31 14:00:57 2012
@@ -1,5 +1,7 @@
 package org.apache.aries.subsystem.core.internal;
 
+import java.io.File;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.MalformedURLException;
@@ -24,6 +26,7 @@ import org.apache.aries.subsystem.core.a
 import org.apache.aries.util.filesystem.FileSystem;
 import org.apache.aries.util.filesystem.IDirectory;
 import org.apache.aries.util.filesystem.IFile;
+import org.apache.aries.util.io.IOUtils;
 import org.apache.aries.util.manifest.ManifestProcessor;
 import org.osgi.framework.Version;
 import org.osgi.framework.namespace.BundleNamespace;
@@ -34,6 +37,7 @@ import org.osgi.resource.Resource;
 import org.osgi.service.repository.Repository;
 import org.osgi.service.resolver.ResolutionException;
 import org.osgi.service.subsystem.SubsystemConstants;
+import org.osgi.service.subsystem.SubsystemException;
 
 public class RawSubsystemResource implements Resource {
 	private static final Pattern PATTERN = Pattern.compile("([^@]+)(?:@(.+))?.esa");
@@ -74,7 +78,8 @@ public class RawSubsystemResource implem
 	
 	private final List<Capability> capabilities;
 	private final DeploymentManifest deploymentManifest;
-	private final IDirectory directory;
+	private final File directory;
+	private final long id;
 	private final Repository localRepository;
 	private final Location location;
 	private final List<Requirement> requirements;
@@ -85,15 +90,32 @@ public class RawSubsystemResource implem
 		this.location = new Location(location);
 		if (content == null)
 			content = this.location.open();
-		directory = FileSystem.getFSRoot(content);
-		resources = computeResources();
-		localRepository = computeLocalRepository();
-		SubsystemManifest manifest = computeSubsystemManifest(directory);
-		manifest = computeSubsystemManifestBeforeRequirements(manifest);
-		requirements = computeRequirements(manifest);
-		subsystemManifest = computeSubsystemManifestAfterRequirements(manifest);
-		capabilities = computeCapabilities();
-		deploymentManifest = computeDeploymentManifest();
+		id = SubsystemIdentifier.getNextId();
+		directory = new File(Activator.getInstance().getBundleContext().getDataFile(""), Long.toString(id));
+		if (!directory.mkdir())
+			throw new SubsystemException("Unable to make directory " + directory.getAbsolutePath());
+		File file = new File(directory, Long.toString(id) + ".ssa");
+		FileOutputStream fos = new FileOutputStream(file);
+		try {
+			IOUtils.copy(content, fos);
+		}
+		finally {
+			IOUtils.close(fos);
+		}
+		IDirectory idir = FileSystem.getFSRoot(file);
+		try {
+			resources = computeResources(idir);
+			localRepository = computeLocalRepository();
+			SubsystemManifest manifest = computeSubsystemManifest(idir);
+			manifest = computeSubsystemManifestBeforeRequirements(manifest);
+			requirements = computeRequirements(manifest);
+			subsystemManifest = computeSubsystemManifestAfterRequirements(manifest);
+			capabilities = computeCapabilities();
+			deploymentManifest = computeDeploymentManifest(idir);
+		}
+		finally {
+			IOUtils.close(idir.toCloseable());
+		}
 	}
 
 	@Override
@@ -112,6 +134,14 @@ public class RawSubsystemResource implem
 		return deploymentManifest;
 	}
 	
+	public File getDirectory() {
+		return directory;
+	}
+	
+	public long getId() {
+		return id;
+	}
+	
 	public Repository getLocalRepository() {
 		return localRepository;
 	}
@@ -177,11 +207,11 @@ public class RawSubsystemResource implem
 		return subsystemManifest.toCapabilities(this);
 	}
 	
-	private DeploymentManifest computeDeploymentManifest() throws IOException {
-		return computeExistingDeploymentManifest();
+	private DeploymentManifest computeDeploymentManifest(IDirectory directory) throws IOException {
+		return computeExistingDeploymentManifest(directory);
 	}
 	
-	private DeploymentManifest computeExistingDeploymentManifest() throws IOException {
+	private DeploymentManifest computeExistingDeploymentManifest(IDirectory directory) throws IOException {
 		Manifest manifest = ManifestProcessor.obtainManifestFromAppDir(directory, "OSGI-INF/DEPLOYMENT.MF");
 		if (manifest == null)
 			return null;
@@ -258,7 +288,7 @@ public class RawSubsystemResource implem
 		return new DependencyCalculator(resources).calculateDependencies();
 	}
 	
-	private Collection<Resource> computeResources() throws IOException, URISyntaxException, UnsupportedOperationException, ResolutionException {
+	private Collection<Resource> computeResources(IDirectory directory) throws IOException, URISyntaxException, UnsupportedOperationException, ResolutionException {
 		List<IFile> files = directory.listFiles();
 		if (files.isEmpty())
 			return Collections.emptyList();

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=1344727&r1=1344726&r2=1344727&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 Thu May 31 14:00:57 2012
@@ -11,6 +11,7 @@ import java.util.jar.Manifest;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleException;
 import org.osgi.framework.Version;
+import org.osgi.framework.wiring.BundleRevision;
 
 public class RegionContextBundleHelper {
 	public static final String SYMBOLICNAME_PREFIX = Constants.RegionContextBundleSymbolicNamePrefix;
@@ -24,6 +25,7 @@ public class RegionContextBundleHelper {
 			return;
 		ThreadLocalSubsystem.set(subsystem);
 		b = subsystem.getRegion().installBundleAtLocation(location, createRegionContextBundle(symbolicName));
+		subsystem.installResource(b.adapt(BundleRevision.class));
 		// The region context bundle must be started persistently.
 		b.start();
 	}
@@ -33,12 +35,15 @@ public class RegionContextBundleHelper {
 		Bundle bundle = subsystem.getRegion().getBundle(symbolicName, VERSION);
 		if (bundle == null)
 			throw new IllegalStateException("Missing region context bundle: " + symbolicName);
+		ThreadLocalSubsystem.set(subsystem);
+		BundleRevision revision = bundle.adapt(BundleRevision.class);
 		try {
 			bundle.uninstall();
 		}
 		catch (BundleException e) {
 			// TODO Should we really eat this? At least log it?
 		}
+		ResourceUninstaller.newInstance(revision, subsystem).uninstall();
 	}
 	
 	private static Manifest createManifest(String symbolicName) {

Added: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResourceInstaller.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResourceInstaller.java?rev=1344727&view=auto
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResourceInstaller.java (added)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResourceInstaller.java Thu May 31 14:00:57 2012
@@ -0,0 +1,64 @@
+package org.apache.aries.subsystem.core.internal;
+
+import org.osgi.resource.Resource;
+import org.osgi.service.coordinator.Coordination;
+import org.osgi.service.coordinator.Participant;
+
+public abstract class ResourceInstaller {
+	protected final Coordination coordination;
+	protected final AriesSubsystem provisionTo;
+	protected final Resource resource;
+	protected final AriesSubsystem subsystem;
+	
+	public ResourceInstaller(Coordination coordination, Resource resource, AriesSubsystem subsystem, boolean transitive) {
+		this.coordination = coordination;
+		this.resource = resource;
+		this.subsystem = subsystem;
+		if (transitive)
+			provisionTo = Utils.findFirstSubsystemAcceptingDependenciesStartingFrom(subsystem);
+		else
+			provisionTo = subsystem;
+	}
+	
+	protected void addConstituent(final Resource resource) {
+		Activator.getInstance().getSubsystems().addConstituent(provisionTo, resource);
+		coordination.addParticipant(new Participant() {
+			@Override
+			public void ended(Coordination arg0) throws Exception {
+				// Nothing
+			}
+
+			@Override
+			public void failed(Coordination arg0) throws Exception {
+				Activator.getInstance().getSubsystems().removeConstituent(provisionTo, resource);
+			}
+		});
+	}
+	
+	protected void addReference(final Resource resource) {
+		Activator.getInstance().getSubsystems().addReference(subsystem, resource);
+		coordination.addParticipant(new Participant() {
+			@Override
+			public void ended(Coordination arg0) throws Exception {
+				// Nothing
+			}
+
+			@Override
+			public void failed(Coordination arg0) throws Exception {
+				Activator.getInstance().getSubsystems().removeReference(subsystem, resource);
+			}
+		});
+	}
+	
+	protected String getLocation() {
+		return provisionTo.getSubsystemId() + "@" + provisionTo.getSymbolicName() + "@" + ResourceHelper.getSymbolicNameAttribute(resource);
+	}
+	
+	protected void removeConstituent() {
+		Activator.getInstance().getSubsystems().removeConstituent(provisionTo, resource);
+	}
+	
+	protected void removeReference() {
+		Activator.getInstance().getSubsystems().removeReference(subsystem, resource);
+	}
+}

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResourceReferences.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResourceReferences.java?rev=1344727&r1=1344726&r2=1344727&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResourceReferences.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResourceReferences.java Thu May 31 14:00:57 2012
@@ -9,46 +9,45 @@ import java.util.Map;
 import java.util.Set;
 
 import org.osgi.resource.Resource;
-import org.osgi.service.subsystem.Subsystem;
 
 public class ResourceReferences {
-	private final Map<Resource, Set<Subsystem>> resourceToSubsystems = new HashMap<Resource, Set<Subsystem>>();
-	private final Map<Subsystem, Set<Resource>> subsystemToResources = new HashMap<Subsystem, Set<Resource>>();
+	private final Map<Resource, Set<AriesSubsystem>> resourceToSubsystems = new HashMap<Resource, Set<AriesSubsystem>>();
+	private final Map<AriesSubsystem, Set<Resource>> subsystemToResources = new HashMap<AriesSubsystem, Set<Resource>>();
 	
-	public synchronized void addReference(Subsystem subsystem, Resource resource) {
+	public synchronized void addReference(AriesSubsystem subsystem, Resource resource) {
 		addSubsystemToResource(subsystem, resource);
 		addResourceToSubsystem(subsystem, resource);
 	}
 	
-	public synchronized Collection<Resource> getResources(Subsystem subsystem) {
+	public synchronized Collection<Resource> getResources(AriesSubsystem subsystem) {
 		Collection<Resource> result = subsystemToResources.get(subsystem);
 		if (result == null)
 			result = Collections.emptyList();
 		return Collections.unmodifiableCollection(new ArrayList<Resource>(result));
 	}
 	
-	public synchronized Collection<Subsystem> getSubsystems(Resource resource) {
-		Collection<Subsystem> result = resourceToSubsystems.get(resource);
+	public synchronized Collection<AriesSubsystem> getSubsystems(Resource resource) {
+		Collection<AriesSubsystem> result = resourceToSubsystems.get(resource);
 		if (result == null)
 			result = Collections.emptyList();
-		return Collections.unmodifiableCollection(new ArrayList<Subsystem>(result));
+		return Collections.unmodifiableCollection(new ArrayList<AriesSubsystem>(result));
 	}
 	
-	public synchronized void removeReference(Subsystem subsystem, Resource resource) {
+	public synchronized void removeReference(AriesSubsystem subsystem, Resource resource) {
 		removeResourceToSubsystem(subsystem, resource);
 		removeSubsystemToResource(subsystem, resource);
 	}
 	
-	private void addResourceToSubsystem(Subsystem subsystem, Resource resource) {
-		Set<Subsystem> subsystems = resourceToSubsystems.get(resource);
+	private void addResourceToSubsystem(AriesSubsystem subsystem, Resource resource) {
+		Set<AriesSubsystem> subsystems = resourceToSubsystems.get(resource);
 		if (subsystems == null) {
-			subsystems = new HashSet<Subsystem>();
+			subsystems = new HashSet<AriesSubsystem>();
 			resourceToSubsystems.put(resource, subsystems);
 		}
 		subsystems.add(subsystem);
 	}
 	
-	private void addSubsystemToResource(Subsystem subsystem, Resource resource) {
+	private void addSubsystemToResource(AriesSubsystem subsystem, Resource resource) {
 		Set<Resource> resources = subsystemToResources.get(subsystem);
 		if (resources == null) {
 			resources = new HashSet<Resource>();
@@ -57,8 +56,8 @@ public class ResourceReferences {
 		resources.add(resource);
 	}
 	
-	private void removeResourceToSubsystem(Subsystem subsystem, Resource resource) {
-		Set<Subsystem> subsystems = resourceToSubsystems.get(resource);
+	private void removeResourceToSubsystem(AriesSubsystem subsystem, Resource resource) {
+		Set<AriesSubsystem> subsystems = resourceToSubsystems.get(resource);
 		if (subsystems == null)
 			return;
 		subsystems.remove(subsystem);
@@ -66,7 +65,7 @@ public class ResourceReferences {
 			resourceToSubsystems.remove(resource);
 	}
 	
-	private void removeSubsystemToResource(Subsystem subsystem, Resource resource) {
+	private void removeSubsystemToResource(AriesSubsystem subsystem, Resource resource) {
 		Set<Resource> resources = subsystemToResources.get(subsystem);
 		if (resources == null)
 			return;

Added: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResourceUninstaller.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResourceUninstaller.java?rev=1344727&view=auto
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResourceUninstaller.java (added)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResourceUninstaller.java Thu May 31 14:00:57 2012
@@ -0,0 +1,73 @@
+package org.apache.aries.subsystem.core.internal;
+
+import org.apache.aries.subsystem.core.archive.ProvisionResourceHeader;
+import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.resource.Resource;
+import org.osgi.service.subsystem.SubsystemConstants;
+import org.osgi.service.subsystem.SubsystemException;
+
+public abstract class ResourceUninstaller {
+	public static ResourceUninstaller newInstance(Resource resource) {
+		return newInstance(resource, null);
+	}
+	
+	public static ResourceUninstaller newInstance(Resource resource, AriesSubsystem subsystem) {
+		String type = ResourceHelper.getTypeAttribute(resource);
+		if (SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION.equals(type)
+				|| SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE.equals(type)
+				|| SubsystemConstants.SUBSYSTEM_TYPE_FEATURE.equals(type))
+			return new SubsystemResourceUninstaller(resource, subsystem);
+		else if (IdentityNamespace.TYPE_BUNDLE.equals(type) || IdentityNamespace.TYPE_FRAGMENT.equals(type))
+			return new BundleResourceUninstaller(resource, subsystem);
+		else
+			throw new SubsystemException("No uninstaller exists for resource type: " + type);
+	}
+	
+	protected static void removeConstituent(AriesSubsystem subsystem, Resource resource) {
+		Activator.getInstance().getSubsystems().removeConstituent(subsystem, resource);
+	}
+	
+	protected static void removeReference(AriesSubsystem subsystem, Resource resource) {
+		Activator.getInstance().getSubsystems().removeReference(subsystem, resource);
+	}
+	
+	protected final AriesSubsystem provisionTo;
+	protected final Resource resource;
+	protected final AriesSubsystem subsystem;
+	
+	public ResourceUninstaller(Resource resource, AriesSubsystem subsystem) {
+		this.resource = resource;
+		this.subsystem = subsystem;
+		if (isTransitive())
+			provisionTo = Utils.findFirstSubsystemAcceptingDependenciesStartingFrom(subsystem);
+		else
+			provisionTo = subsystem;
+	}
+	
+	public abstract void uninstall();
+	
+	protected boolean isImplicit() {
+		return subsystem != null;
+	}
+	
+	protected boolean isTransitive() {
+		if (subsystem == null)
+			return false;
+		ProvisionResourceHeader header = subsystem.getArchive().getDeploymentManifest().getProvisionResourceHeader();
+		if (header == null)
+			return false;
+		return header.contains(resource);
+	}
+	
+	protected boolean isResourceUninstallable() {
+		return Activator.getInstance().getSubsystems().getSubsystemsReferencing(resource).size() <= 1;
+	}
+	
+	protected void removeConstituent() {
+		removeConstituent(provisionTo, resource);
+	}
+	
+	protected void removeReference() {
+		removeReference(subsystem, resource);
+	}
+}

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/StartAction.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/StartAction.java?rev=1344727&r1=1344726&r2=1344727&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/StartAction.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/StartAction.java Thu May 31 14:00:57 2012
@@ -41,7 +41,7 @@ public class StartAction implements Priv
 				.getCoordinator()
 				.create(subsystem.getSymbolicName() + '-' + subsystem.getSubsystemId(), 0);
 		try {
-			List<Resource> resources = new ArrayList<Resource>(AriesSubsystem.resourceReferences.getResources(subsystem));
+			List<Resource> resources = new ArrayList<Resource>(Activator.getInstance().getSubsystems().getResourcesReferencedBy(subsystem));
 			if (subsystem.resource != null)
 				Collections.sort(resources, new StartResourceComparator(subsystem.resource.getSubsystemManifest().getSubsystemContentHeader()));
 			for (Resource resource : resources)

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemGraph.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemGraph.java?rev=1344727&r1=1344726&r2=1344727&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemGraph.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemGraph.java Thu May 31 14:00:57 2012
@@ -89,14 +89,20 @@ public class SubsystemGraph {
 		return Collections.unmodifiableCollection(result);
 	}
 	
-	public synchronized void remove(AriesSubsystem subsystem) {
-		SubsystemWrapper subsystemWrap = new SubsystemWrapper(subsystem);
+	public synchronized void remove(AriesSubsystem child) {
+		SubsystemWrapper subsystemWrap = new SubsystemWrapper(child);
 		Collection<SubsystemWrapper> parents = getParents(subsystemWrap);
 		for (SubsystemWrapper parent : parents)
 			adjacencyList.get(parent).remove(subsystemWrap);
 		adjacencyList.remove(subsystemWrap);
 	}
 	
+	public synchronized void remove(AriesSubsystem parent, AriesSubsystem child) {
+		SubsystemWrapper parentWrap = new SubsystemWrapper(parent);
+		SubsystemWrapper childWrap = new SubsystemWrapper(child);
+		adjacencyList.get(parentWrap).remove(childWrap);
+	}
+	
 	private boolean containsAncestor(SubsystemWrapper subsystem, SubsystemWrapper ancestor) {
 		Collection<SubsystemWrapper> subsystems = adjacencyList.get(subsystem);
 		if (subsystems == null)

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=1344727&r1=1344726&r2=1344727&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 Thu May 31 14:00:57 2012
@@ -39,7 +39,7 @@ public class SubsystemResolverHook imple
 		// there is at least one preferred provider.
 		// (1) Find the subsystem(s) containing requirement.getResource() as a
 		// constituent.
-		Collection<AriesSubsystem> requirers = AriesSubsystem.getSubsystems(requirement.getResource());
+		Collection<AriesSubsystem> requirers = Activator.getInstance().getSubsystems().getSubsystemsReferencing(requirement.getResource());
 		// (2) For each candidate, ask each subsystem if the candidate or any of
 		// the candidate's containing subsystems is a preferred provider. If at
 		// least one preferred provider exists, filter out all other candidates
@@ -62,7 +62,7 @@ public class SubsystemResolverHook imple
 				if (revision.getSymbolicName().startsWith(Constants.RegionContextBundleSymbolicNamePrefix))
 					// Don't want to filter out the region context bundle.
 					continue;
-				Collection<AriesSubsystem> subsystems = AriesSubsystem.getSubsystems(revision);
+				Collection<AriesSubsystem> subsystems = Activator.getInstance().getSubsystems().getSubsystemsReferencing(revision);
 				for (AriesSubsystem subsystem : subsystems) {
 					if (subsystem.isFeature()) {
 						// Feature subsystems require no isolation.
@@ -87,7 +87,7 @@ public class SubsystemResolverHook imple
 	}
 	
 	private boolean isResourceConstituentOfPreferredSubsystem(Resource resource, AriesSubsystem preferer) {
-		Collection<AriesSubsystem> subsystems = AriesSubsystem.getSubsystems(resource);
+		Collection<AriesSubsystem> subsystems = Activator.getInstance().getSubsystems().getSubsystemsReferencing(resource);
 		for (AriesSubsystem subsystem : subsystems)
 			if (preferer.getArchive().getSubsystemManifest().getPreferredProviderHeader().contains(subsystem))
 				return true;

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResource.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResource.java?rev=1344727&r1=1344726&r2=1344727&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResource.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResource.java Thu May 31 14:00:57 2012
@@ -1,5 +1,6 @@
 package org.apache.aries.subsystem.core.internal;
 
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URISyntaxException;
@@ -62,6 +63,14 @@ public class SubsystemResource implement
 		return deploymentManifest;
 	}
 	
+	public File getDirectory() {
+		return resource.getDirectory();
+	}
+	
+	public long getId() {
+		return resource.getId();
+	}
+	
 	public Collection<Resource> getInstallableContent() {
 		return installableContent;
 	}
@@ -278,7 +287,7 @@ public class SubsystemResource implement
 			if (map.containsKey(requirement)) {
 				Collection<Capability> capabilities = map.get(requirement);
 				for (Capability capability : capabilities) {
-					Collection<AriesSubsystem> subsystems = AriesSubsystem.getSubsystems(capability.getResource());
+					Collection<AriesSubsystem> subsystems = Activator.getInstance().getSubsystems().getSubsystemsReferencing(capability.getResource());
 					if (!subsystems.isEmpty())
 						if (subsystems.iterator().next().getRegion().equals(parent.getRegion()))
 							return capability.getResource();
@@ -297,13 +306,6 @@ public class SubsystemResource implement
 		return null;
 	}
 	
-	private AriesSubsystem findFirstSubsystemAcceptingDependencies() {
-		AriesSubsystem subsystem = parent;
-		while (!isAcceptDependencies(subsystem))
-			subsystem = (AriesSubsystem)subsystem.getParents().iterator().next();
-		return subsystem;
-	}
-	
 	private Collection<Resource> getContentResources() {
 		Collection<Resource> result = new ArrayList<Resource>(installableContent.size() + sharedContent.size());
 		result.addAll(installableContent);
@@ -318,10 +320,6 @@ public class SubsystemResource implement
 		return result;
 	}
 	
-	private boolean isAcceptDependencies(AriesSubsystem subsystem) {
-		return subsystem.getArchive().getSubsystemManifest().getSubsystemTypeHeader().getProvisionPolicyDirective().isAcceptDependencies();
-	}
-	
 	private boolean isInstallable(Resource resource) {
 		return !isShared(resource);
 	}
@@ -350,9 +348,9 @@ public class SubsystemResource implement
 	private boolean isValid(Capability capability) {
 		AriesSubsystem subsystem;
 		if (isInstallable(capability.getResource()))
-			subsystem = findFirstSubsystemAcceptingDependencies();
+			subsystem = Utils.findFirstSubsystemAcceptingDependenciesStartingFrom(parent);
 		else
-			subsystem = AriesSubsystem.getSubsystems(capability.getResource()).iterator().next();
+			subsystem = Activator.getInstance().getSubsystems().getSubsystemsReferencing(capability.getResource()).iterator().next();
 		return new SharingPolicyValidator(subsystem.getRegion(), parent.getRegion()).isValid(capability);
 	}
 }

Added: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResourceInstaller.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResourceInstaller.java?rev=1344727&view=auto
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResourceInstaller.java (added)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResourceInstaller.java Thu May 31 14:00:57 2012
@@ -0,0 +1,47 @@
+package org.apache.aries.subsystem.core.internal;
+
+import java.security.AccessController;
+
+import org.osgi.resource.Resource;
+import org.osgi.service.coordinator.Coordination;
+import org.osgi.service.coordinator.Participant;
+import org.osgi.service.repository.RepositoryContent;
+
+public class SubsystemResourceInstaller extends ResourceInstaller {
+	public SubsystemResourceInstaller(Coordination coordination, Resource resource, AriesSubsystem subsystem, boolean transitive) {
+		super(coordination, resource, subsystem, transitive);
+	}
+	
+	public void install() throws Exception {
+		final AriesSubsystem subsystem;
+		if (resource instanceof RepositoryContent) {
+			AccessController.doPrivileged(new InstallAction(getLocation(), ((RepositoryContent)resource).getContent(), provisionTo, null, coordination, true));
+			return;
+		}
+		else if (resource instanceof AriesSubsystem)
+			subsystem = (AriesSubsystem)resource;
+		else if (resource instanceof RawSubsystemResource)
+			subsystem = new AriesSubsystem(new SubsystemResource((RawSubsystemResource)resource, provisionTo), provisionTo);
+		else
+			subsystem = new AriesSubsystem((SubsystemResource)resource, provisionTo);
+		addChild(subsystem);
+		addConstituent(subsystem);
+		addReference(subsystem);
+		subsystem.install(coordination, provisionTo);
+	}
+	
+	private void addChild(final AriesSubsystem child) {
+		Activator.getInstance().getSubsystems().addChild(subsystem, child);
+		coordination.addParticipant(new Participant() {
+			@Override
+			public void ended(Coordination arg0) throws Exception {
+				// Nothing
+			}
+
+			@Override
+			public void failed(Coordination arg0) throws Exception {
+				Activator.getInstance().getSubsystems().removeChild(subsystem, child);
+			}
+		});
+	}
+}