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/06/24 21:48:45 UTC

svn commit: r1353319 [2/3] - 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...

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/GetBundleContextAction.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/GetBundleContextAction.java?rev=1353319&r1=1353318&r2=1353319&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/GetBundleContextAction.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/GetBundleContextAction.java Sun Jun 24 19:48:40 2012
@@ -18,7 +18,7 @@ public class GetBundleContextAction impl
 		if (EnumSet.of(State.INSTALL_FAILED, State.UNINSTALLED).contains(
 				subsystem.getState()))
 			return null;
-		AriesSubsystem subsystem = this.subsystem.findScopedSubsystemInRegion();
+		AriesSubsystem subsystem = Utils.findScopedSubsystemInRegion(this.subsystem);
 		return subsystem.getRegion().getBundle(
 				RegionContextBundleHelper.SYMBOLICNAME_PREFIX
 						+ subsystem.getSubsystemId(),

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/GetSubsystemHeadersAction.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/GetSubsystemHeadersAction.java?rev=1353319&r1=1353318&r2=1353319&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/GetSubsystemHeadersAction.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/GetSubsystemHeadersAction.java Sun Jun 24 19:48:40 2012
@@ -16,7 +16,7 @@ public class GetSubsystemHeadersAction i
 	
 	@Override
 	public Map<String, String> run() {
-		Map<String, Header<?>> headers = subsystem.getArchive().getSubsystemManifest().getHeaders();
+		Map<String, Header<?>> headers = subsystem.getSubsystemManifest().getHeaders();
 		Map<String, String> result = new HashMap<String, String>(headers.size());
 		for (Entry<String, Header<?>> entry: headers.entrySet()) {
 			Header<?> value = entry.getValue();

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=1353319&r1=1353318&r2=1353319&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 Sun Jun 24 19:48:40 2012
@@ -1,14 +1,19 @@
 package org.apache.aries.subsystem.core.internal;
 
+import java.io.IOException;
 import java.io.InputStream;
+import java.net.URISyntaxException;
 import java.security.AccessControlContext;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 
 import org.apache.aries.util.io.IOUtils;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.service.coordinator.Coordination;
 import org.osgi.service.coordinator.CoordinationException;
 import org.osgi.service.coordinator.Participant;
+import org.osgi.service.resolver.ResolutionException;
 import org.osgi.service.subsystem.SubsystemException;
 
 public class InstallAction implements PrivilegedAction<AriesSubsystem> {
@@ -28,6 +33,8 @@ public class InstallAction implements Pr
 		this.content = content;
 		this.parent = parent;
 		this.context = context;
+		if (coordination == null)
+			coordination = Utils.createCoordination(parent);
 		this.coordination = coordination;
 		this.embedded = embedded;
 	}
@@ -35,23 +42,9 @@ public class InstallAction implements Pr
 	@Override
 	public AriesSubsystem run() {
 		AriesSubsystem result = null;
-		Coordination coordination = this.coordination;
-		if (coordination == null)
-			coordination = Activator.getInstance().getCoordinator().create(parent.getSymbolicName() + '-' + parent.getSubsystemId(), 0);
 		try {
 			TargetRegion region = new TargetRegion(parent);
-			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());
-				}
-			});
+			SubsystemResource ssr = createSubsystemResource(location, content, parent);
 			result = Activator.getInstance().getSubsystems().getSubsystemByLocation(location);
 			if (result != null) {
 				checkLifecyclePermission(result);
@@ -61,8 +54,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.installResource(result);
-				return result;
+				return (AriesSubsystem)ResourceInstaller.newInstance(coordination, result, parent, false).install();
 			}
 			result = (AriesSubsystem)region.find(
 					ssr.getSubsystemManifest().getSubsystemSymbolicNameHeader().getSymbolicName(), 
@@ -71,12 +63,11 @@ 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.installResource(result);
-				return result;
+				return (AriesSubsystem)ResourceInstaller.newInstance(coordination, result, parent, false).install();
 			}
-			result = new AriesSubsystem(ssr, parent);
+			result = createSubsystem(ssr);
 			checkLifecyclePermission(result);
-			parent.installResource(result, coordination, false);
+			return (AriesSubsystem)ResourceInstaller.newInstance(coordination, result, parent, false).install();
 		}
 		catch (Throwable t) {
 			coordination.fail(t);
@@ -109,4 +100,37 @@ public class InstallAction implements Pr
 		},
 		context);
 	}
+	
+	private AriesSubsystem createSubsystem(SubsystemResource resource) throws URISyntaxException, IOException, BundleException, InvalidSyntaxException {
+		final AriesSubsystem result = new AriesSubsystem(resource);
+		coordination.addParticipant(new Participant() {
+			@Override
+			public void ended(Coordination c) throws Exception {
+				// Nothing
+			}
+
+			@Override
+			public void failed(Coordination c) throws Exception {
+				IOUtils.deleteRecursive(result.getDirectory());
+			}
+		});
+		return result;
+		
+	}
+	
+	private SubsystemResource createSubsystemResource(String location, InputStream content, AriesSubsystem parent) throws URISyntaxException, IOException, ResolutionException {
+		final SubsystemResource result = 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(result.getDirectory());
+//			}
+//		});
+		return result;
+	}
 }

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/PreferredProviderRepository.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/PreferredProviderRepository.java?rev=1353319&r1=1353318&r2=1353319&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/PreferredProviderRepository.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/PreferredProviderRepository.java Sun Jun 24 19:48:40 2012
@@ -89,6 +89,6 @@ public class PreferredProviderRepository
 	}
 	
 	private boolean isValid(Capability capability) {
-		return resource.getParent().getConstituents().contains(capability.getResource());
+		return resource.getParents().iterator().next().getConstituents().contains(capability.getResource());
 	}
 }

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=1353319&r1=1353318&r2=1353319&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 Sun Jun 24 19:48:40 2012
@@ -1,7 +1,6 @@
 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;
@@ -22,6 +21,7 @@ import org.apache.aries.subsystem.core.a
 import org.apache.aries.subsystem.core.archive.SubsystemContentHeader;
 import org.apache.aries.subsystem.core.archive.SubsystemManifest;
 import org.apache.aries.subsystem.core.archive.SubsystemSymbolicNameHeader;
+import org.apache.aries.subsystem.core.archive.SubsystemTypeHeader;
 import org.apache.aries.subsystem.core.archive.SubsystemVersionHeader;
 import org.apache.aries.util.filesystem.FileSystem;
 import org.apache.aries.util.filesystem.IDirectory;
@@ -37,7 +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;
+import org.osgi.service.subsystem.Subsystem.State;
 
 public class RawSubsystemResource implements Resource {
 	private static final Pattern PATTERN = Pattern.compile("([^@]+)(?:@(.+))?.esa");
@@ -78,8 +78,6 @@ public class RawSubsystemResource implem
 	
 	private final List<Capability> capabilities;
 	private final DeploymentManifest deploymentManifest;
-	private final File directory;
-	private final long id;
 	private final Repository localRepository;
 	private final Location location;
 	private final List<Requirement> requirements;
@@ -90,19 +88,7 @@ public class RawSubsystemResource implem
 		this.location = new Location(location);
 		if (content == null)
 			content = this.location.open();
-		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);
+		IDirectory idir = FileSystem.getFSRoot(content);
 		try {
 			resources = computeResources(idir);
 			localRepository = computeLocalRepository();
@@ -117,6 +103,20 @@ public class RawSubsystemResource implem
 			IOUtils.close(idir.toCloseable());
 		}
 	}
+	
+	public RawSubsystemResource(File file) throws IOException, URISyntaxException, ResolutionException {
+		this(FileSystem.getFSRoot(file));
+	}
+	
+	public RawSubsystemResource(IDirectory idir) throws IOException, URISyntaxException, ResolutionException {
+		resources = Collections.emptyList();
+		localRepository = computeLocalRepository();
+		subsystemManifest = initializeSubsystemManifest(idir);
+		requirements = subsystemManifest.toRequirements(this);
+		capabilities = subsystemManifest.toCapabilities(this);
+		deploymentManifest = initializeDeploymentManifest(idir);
+		location = new Location(deploymentManifest.getHeaders().get(DeploymentManifest.ARIESSUBSYSTEM_LOCATION).getValue());
+	}
 
 	@Override
 	public List<Capability> getCapabilities(String namespace) {
@@ -134,14 +134,6 @@ public class RawSubsystemResource implem
 		return deploymentManifest;
 	}
 	
-	public File getDirectory() {
-		return directory;
-	}
-	
-	public long getId() {
-		return id;
-	}
-	
 	public Repository getLocalRepository() {
 		return localRepository;
 	}
@@ -288,7 +280,7 @@ public class RawSubsystemResource implem
 		return new DependencyCalculator(resources).calculateDependencies();
 	}
 	
-	private Collection<Resource> computeResources(IDirectory directory) throws IOException, URISyntaxException, UnsupportedOperationException, ResolutionException {
+	private Collection<Resource> computeResources(IDirectory directory) throws IOException, URISyntaxException, ResolutionException {
 		List<IFile> files = directory.listFiles();
 		if (files.isEmpty())
 			return Collections.emptyList();
@@ -343,6 +335,39 @@ public class RawSubsystemResource implem
 		return header;
 	}
 	
+	private DeploymentManifest initializeDeploymentManifest(IDirectory idir)
+			throws IOException {
+		Manifest manifest = ManifestProcessor.obtainManifestFromAppDir(idir,
+				"OSGI-INF/DEPLOYMENT.MF");
+		if (manifest != null)
+			return new DeploymentManifest(manifest);
+		else
+			return new DeploymentManifest.Builder()
+					.manifest(getSubsystemManifest())
+					.location(AriesSubsystem.ROOT_LOCATION).autostart(true).id(0)
+					.lastId(SubsystemIdentifier.getLastId())
+					.region(AriesSubsystem.ROOT_REGION).state(State.INSTALLING)
+					.build();
+	}
+	
+	private SubsystemManifest initializeSubsystemManifest(IDirectory idir)
+			throws IOException {
+		Manifest manifest = ManifestProcessor.obtainManifestFromAppDir(idir,
+				"OSGI-INF/SUBSYSTEM.MF");
+		if (manifest != null)
+			return new SubsystemManifest(manifest);
+		else
+			return new SubsystemManifest.Builder()
+					.symbolicName(AriesSubsystem.ROOT_SYMBOLIC_NAME)
+					.version(AriesSubsystem.ROOT_VERSION)
+					.type(SubsystemTypeHeader.TYPE_APPLICATION
+							+ ';'
+							+ SubsystemTypeHeader.DIRECTIVE_PROVISION_POLICY
+							+ ":="
+							+ SubsystemTypeHeader.PROVISION_POLICY_ACCEPT_DEPENDENCIES)
+					.build();
+	}
+	
 	private boolean isComposite(SubsystemManifest manifest) {
 		return SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE.equals(manifest.getSubsystemTypeHeader().getType());
 	}

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=1353319&r1=1353318&r2=1353319&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 Sun Jun 24 19:48:40 2012
@@ -21,11 +21,11 @@ public class RegionContextBundleHelper {
 		String symbolicName = SYMBOLICNAME_PREFIX + subsystem.getSubsystemId();
 		String location = subsystem.getLocation() + '/' + subsystem.getSubsystemId();
 		Bundle b = subsystem.getRegion().getBundle(symbolicName, VERSION);
-		if (b != null)
-			return;
-		ThreadLocalSubsystem.set(subsystem);
-		b = subsystem.getRegion().installBundleAtLocation(location, createRegionContextBundle(symbolicName));
-		subsystem.installResource(b.adapt(BundleRevision.class));
+		if (b == null) {
+			ThreadLocalSubsystem.set(subsystem);
+			b = subsystem.getRegion().installBundleAtLocation(location, createRegionContextBundle(symbolicName));
+		}
+		Utils.installResource(b.adapt(BundleRevision.class), subsystem);
 		// The region context bundle must be started persistently.
 		b.start();
 	}

Modified: 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=1353319&r1=1353318&r2=1353319&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResourceInstaller.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResourceInstaller.java Sun Jun 24 19:48:40 2012
@@ -1,10 +1,25 @@
 package org.apache.aries.subsystem.core.internal;
 
+import org.osgi.framework.namespace.IdentityNamespace;
 import org.osgi.resource.Resource;
 import org.osgi.service.coordinator.Coordination;
 import org.osgi.service.coordinator.Participant;
+import org.osgi.service.subsystem.SubsystemConstants;
+import org.osgi.service.subsystem.SubsystemException;
 
 public abstract class ResourceInstaller {
+	public static ResourceInstaller newInstance(Coordination coordination, Resource resource, AriesSubsystem subsystem, boolean transitive) {
+		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 SubsystemResourceInstaller(coordination, resource, subsystem, transitive);
+		else if (IdentityNamespace.TYPE_BUNDLE.equals(type) || IdentityNamespace.TYPE_FRAGMENT.equals(type))
+			return new BundleResourceInstaller(coordination, resource, subsystem, transitive);
+		else
+			throw new SubsystemException("No installer exists for resource type: " + type);
+	}
+	
 	protected final Coordination coordination;
 	protected final AriesSubsystem provisionTo;
 	protected final Resource resource;
@@ -14,13 +29,21 @@ public abstract class ResourceInstaller 
 		this.coordination = coordination;
 		this.resource = resource;
 		this.subsystem = subsystem;
-		if (transitive)
-			provisionTo = Utils.findFirstSubsystemAcceptingDependenciesStartingFrom(subsystem);
+		if (transitive) {
+			if (Utils.isInstallableResource(resource))
+				provisionTo = Utils.findFirstSubsystemAcceptingDependenciesStartingFrom(subsystem);
+			else
+				provisionTo = null;
+		}
 		else
 			provisionTo = subsystem;
 	}
 	
+	public abstract Resource install() throws Exception;
+	
 	protected void addConstituent(final Resource resource) {
+		if (provisionTo == null)
+			return;
 		Activator.getInstance().getSubsystems().addConstituent(provisionTo, resource);
 		coordination.addParticipant(new Participant() {
 			@Override
@@ -36,6 +59,8 @@ public abstract class ResourceInstaller 
 	}
 	
 	protected void addReference(final Resource resource) {
+		if (subsystem == null)
+			return;
 		Activator.getInstance().getSubsystems().addReference(subsystem, resource);
 		coordination.addParticipant(new Participant() {
 			@Override
@@ -53,12 +78,4 @@ public abstract class ResourceInstaller 
 	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/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=1353319&r1=1353318&r2=1353319&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResourceUninstaller.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResourceUninstaller.java Sun Jun 24 19:48:40 2012
@@ -53,7 +53,7 @@ public abstract class ResourceUninstalle
 	protected boolean isTransitive() {
 		if (subsystem == null)
 			return false;
-		ProvisionResourceHeader header = subsystem.getArchive().getDeploymentManifest().getProvisionResourceHeader();
+		ProvisionResourceHeader header = subsystem.getDeploymentManifest().getProvisionResourceHeader();
 		if (header == null)
 			return false;
 		return header.contains(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=1353319&r1=1353318&r2=1353319&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 Sun Jun 24 19:48:40 2012
@@ -1,21 +1,46 @@
 package org.apache.aries.subsystem.core.internal;
 
-import java.security.PrivilegedAction;
+import java.io.IOException;
+import java.net.URISyntaxException;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map.Entry;
 
+import org.apache.aries.subsystem.core.archive.ExportPackageCapability;
+import org.apache.aries.subsystem.core.archive.ExportPackageHeader;
+import org.apache.aries.subsystem.core.archive.ProvideCapabilityCapability;
+import org.apache.aries.subsystem.core.archive.ProvideCapabilityHeader;
+import org.apache.aries.subsystem.core.archive.SubsystemContentHeader;
+import org.apache.aries.subsystem.core.archive.SubsystemExportServiceCapability;
+import org.apache.aries.subsystem.core.archive.SubsystemExportServiceHeader;
+import org.eclipse.equinox.region.Region;
+import org.eclipse.equinox.region.RegionFilter;
+import org.eclipse.equinox.region.RegionFilterBuilder;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.FrameworkWiring;
 import org.osgi.resource.Resource;
 import org.osgi.service.coordinator.Coordination;
 import org.osgi.service.coordinator.CoordinationException;
-import org.osgi.service.subsystem.SubsystemException;
+import org.osgi.service.coordinator.Participant;
+import org.osgi.service.resolver.ResolutionException;
+import org.osgi.service.subsystem.Subsystem;
 import org.osgi.service.subsystem.Subsystem.State;
+import org.osgi.service.subsystem.SubsystemConstants;
+import org.osgi.service.subsystem.SubsystemException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-public class StartAction implements PrivilegedAction<Object> {
-	private final AriesSubsystem subsystem;
+public class StartAction extends AbstractAction {
+	private static final Logger logger = LoggerFactory.getLogger(AriesSubsystem.class);
 	
 	public StartAction(AriesSubsystem subsystem) {
-		this.subsystem = subsystem;
+		super(subsystem);
 	}
 	
 	@Override
@@ -24,16 +49,16 @@ public class StartAction implements Priv
 		if (state == State.UNINSTALLING || state == State.UNINSTALLED)
 			throw new SubsystemException("Cannot stop from state " + state);
 		if (state == State.INSTALLING || state == State.RESOLVING || state == State.STOPPING) {
-			subsystem.waitForStateChange();
+			waitForStateChange();
 			subsystem.start();
 			return null;
 		}
 		// TODO Should we wait on STARTING to see if the outcome is ACTIVE?
 		if (state == State.STARTING || state == State.ACTIVE)
 			return null;
-		subsystem.resolve();
+		resolve(subsystem);
 		subsystem.setState(State.STARTING);
-		subsystem.autostart = true;
+		subsystem.setAutostart(true);
 		// TODO Need to hold a lock here to guarantee that another start
 		// operation can't occur when the state goes to RESOLVED.
 		// Start the subsystem.
@@ -42,10 +67,11 @@ public class StartAction implements Priv
 				.create(subsystem.getSymbolicName() + '-' + subsystem.getSubsystemId(), 0);
 		try {
 			List<Resource> resources = new ArrayList<Resource>(Activator.getInstance().getSubsystems().getResourcesReferencedBy(subsystem));
-			if (!subsystem.isRoot())
-				Collections.sort(resources, new StartResourceComparator(subsystem.getSubsystemManifest().getSubsystemContentHeader()));
+			SubsystemContentHeader header = subsystem.getSubsystemManifest().getSubsystemContentHeader();
+			if (header != null && !subsystem.isRoot())
+				Collections.sort(resources, new StartResourceComparator(header));
 			for (Resource resource : resources)
-				subsystem.startResource(resource, coordination);
+				startResource(resource, coordination);
 			subsystem.setState(State.ACTIVE);
 		} catch (Throwable t) {
 			coordination.fail(t);
@@ -64,4 +90,162 @@ public class StartAction implements Priv
 		}
 		return null;
 	}
+	
+	private Collection<Bundle> getBundles(AriesSubsystem subsystem) {
+		Collection<Resource> constituents = Activator.getInstance().getSubsystems().getConstituents(subsystem);
+		ArrayList<Bundle> result = new ArrayList<Bundle>(constituents.size());
+		for (Resource resource : constituents) {
+			if (resource instanceof BundleRevision)
+				result.add(((BundleRevision)resource).getBundle());
+		}
+		result.trimToSize();
+		return result;
+	}
+	
+	private void resolve(AriesSubsystem subsystem) {
+		if (subsystem.getState() != State.INSTALLED)
+			return;
+		subsystem.setState(State.RESOLVING);
+		try {
+			for (Subsystem child : Activator.getInstance().getSubsystems().getChildren(subsystem))
+				resolve((AriesSubsystem)child);
+			// TODO I think this is insufficient. Do we need both
+			// pre-install and post-install environments for the Resolver?
+			Collection<Bundle> bundles = getBundles(subsystem);
+			if (!Activator.getInstance().getBundleContext().getBundle(0)
+					.adapt(FrameworkWiring.class).resolveBundles(bundles)) {
+				logger.error(
+						"Unable to resolve bundles for subsystem/version/id {}/{}/{}: {}",
+						new Object[] { subsystem.getSymbolicName(), subsystem.getVersion(),
+								subsystem.getSubsystemId(), bundles });
+				throw new SubsystemException("Framework could not resolve the bundles");
+			}
+			setExportIsolationPolicy(subsystem);
+			// TODO Could avoid calling setState (and notifyAll) here and
+			// avoid the need for a lock.
+			subsystem.setState(State.RESOLVED);
+		}
+		catch (Throwable t) {
+			subsystem.setState(State.INSTALLED);
+			if (t instanceof SubsystemException)
+				throw (SubsystemException)t;
+			throw new SubsystemException(t);
+		}
+	}
+	
+	private void setExportIsolationPolicy(AriesSubsystem subsystem) throws InvalidSyntaxException, IOException, BundleException, URISyntaxException, ResolutionException {
+		if (subsystem.isRoot())
+			// Nothing to do if this is the root subsystem.
+			return;
+		if (!subsystem.isScoped())
+			// Features share the same isolation as that of their scoped parent.
+			return;
+		Region from = ((AriesSubsystem)subsystem.getParents().iterator().next()).getRegion();
+		Region to = subsystem.getRegion();
+		RegionFilterBuilder builder = from.getRegionDigraph().createRegionFilterBuilder();
+		if (subsystem.isComposite()) {
+			setExportIsolationPolicy(builder, subsystem.getDeploymentManifest().getExportPackageHeader(), subsystem);
+			setExportIsolationPolicy(builder, subsystem.getDeploymentManifest().getProvideCapabilityHeader(), subsystem);
+			setExportIsolationPolicy(builder, subsystem.getDeploymentManifest().getSubsystemExportServiceHeader(), subsystem);
+			// TODO Implement export isolation policy for composites.
+		}
+		RegionFilter regionFilter = builder.build();
+		if (logger.isDebugEnabled())
+			logger.debug("Establishing region connection: from=" + from
+					+ ", to=" + to + ", filter=" + regionFilter);
+		from.connectRegion(to, regionFilter);
+	}
+	
+	private void setExportIsolationPolicy(RegionFilterBuilder builder, ExportPackageHeader header, AriesSubsystem subsystem) throws InvalidSyntaxException {
+		if (header == null)
+			return;
+		String policy = RegionFilter.VISIBLE_PACKAGE_NAMESPACE;
+		for (ExportPackageCapability capability : header.toCapabilities(subsystem)) {
+			StringBuilder filter = new StringBuilder("(&");
+			for (Entry<String, Object> attribute : capability.getAttributes().entrySet())
+				filter.append('(').append(attribute.getKey()).append('=').append(attribute.getValue()).append(')');
+			filter.append(')');
+			if (logger.isDebugEnabled())
+				logger.debug("Allowing " + policy + " of " + filter);
+			builder.allow(policy, filter.toString());
+		}
+	}
+	
+	private void setExportIsolationPolicy(RegionFilterBuilder builder, ProvideCapabilityHeader header, AriesSubsystem subsystem) throws InvalidSyntaxException {
+		if (header == null)
+			return;
+		for (ProvideCapabilityHeader.Clause clause : header.getClauses()) {
+			ProvideCapabilityCapability capability = new ProvideCapabilityCapability(clause, subsystem);
+			String policy = capability.getNamespace();
+			StringBuilder filter = new StringBuilder("(&");
+			for (Entry<String, Object> attribute : capability.getAttributes().entrySet())
+				filter.append('(').append(attribute.getKey()).append('=').append(attribute.getValue()).append(')');
+			filter.append(')');
+			if (logger.isDebugEnabled())
+				logger.debug("Allowing " + policy + " of " + filter);
+			builder.allow(policy, filter.toString());
+		}
+	}
+	
+	private void setExportIsolationPolicy(RegionFilterBuilder builder, SubsystemExportServiceHeader header, AriesSubsystem subsystem) throws InvalidSyntaxException {
+		if (header == null)
+			return;
+		String policy = RegionFilter.VISIBLE_SERVICE_NAMESPACE;
+		for (SubsystemExportServiceHeader.Clause clause : header.getClauses()) {
+			SubsystemExportServiceCapability capability = new SubsystemExportServiceCapability(clause, subsystem);
+			String filter = capability.getDirectives().get(SubsystemExportServiceCapability.DIRECTIVE_FILTER);
+			if (logger.isDebugEnabled())
+				logger.debug("Allowing " + policy + " of " + filter);
+			builder.allow(policy, filter.toString());
+		}
+	}
+	
+	private void startBundleResource(Resource resource, Coordination coordination) throws BundleException {
+		final Bundle bundle = ((BundleRevision)resource).getBundle();
+		if ((bundle.getState() & (Bundle.STARTING | Bundle.ACTIVE)) != 0)
+			return;
+		bundle.start(Bundle.START_TRANSIENT | Bundle.START_ACTIVATION_POLICY);
+		if (coordination == null)
+			return;
+		coordination.addParticipant(new Participant() {
+			public void ended(Coordination coordination) throws Exception {
+				// noop
+			}
+	
+			public void failed(Coordination coordination) throws Exception {
+				bundle.stop();
+			}
+		});
+	}
+	
+	private 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();
+		if (coordination == null)
+			return;
+		coordination.addParticipant(new Participant() {
+			public void ended(Coordination coordination) throws Exception {
+				// noop
+			}
+	
+			public void failed(Coordination coordination) throws Exception {
+				subsystem.stop();
+			}
+		});
+	}
 }

Added: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/StopAction.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/StopAction.java?rev=1353319&view=auto
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/StopAction.java (added)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/StopAction.java Sun Jun 24 19:48:40 2012
@@ -0,0 +1,108 @@
+package org.apache.aries.subsystem.core.internal;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.aries.subsystem.core.archive.DeploymentManifest;
+import org.apache.aries.subsystem.core.archive.SubsystemContentHeader;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.resource.Resource;
+import org.osgi.service.subsystem.Subsystem.State;
+import org.osgi.service.subsystem.SubsystemConstants;
+import org.osgi.service.subsystem.SubsystemException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class StopAction extends AbstractAction {
+	private static final Logger logger = LoggerFactory.getLogger(StopAction.class);
+	
+	public StopAction(AriesSubsystem subsystem) {
+		super(subsystem);
+	}
+	
+	public StopAction(AriesSubsystem subsystem, boolean disableRootCheck) {
+		super(subsystem, disableRootCheck);
+	}
+	
+	@Override
+	public Object run() {
+		checkRoot();
+		subsystem.setAutostart(false);
+		if (subsystem.getState() == State.UNINSTALLING || subsystem.getState() == State.UNINSTALLED) {
+			throw new SubsystemException("Cannot stop from state " + subsystem.getState());
+		}
+		else if (subsystem.getState() == State.STARTING) {
+			waitForStateChange();
+			subsystem.stop();
+		}
+		else if (subsystem.getState() != State.ACTIVE) {
+			return null;
+		}
+		subsystem.setState(State.STOPPING);
+		// For non-root subsystems, stop any remaining constituents.
+		if (!subsystem.isRoot()){
+			List<Resource> resources = new ArrayList<Resource>(Activator.getInstance().getSubsystems().getResourcesReferencedBy(subsystem));
+			SubsystemContentHeader header = subsystem.getSubsystemManifest().getSubsystemContentHeader();
+			if (header != null) {
+				Collections.sort(resources, new StartResourceComparator(subsystem.getSubsystemManifest().getSubsystemContentHeader()));
+				Collections.reverse(resources);
+			}
+			for (Resource resource : resources) {
+				// Don't stop the region context bundle.
+				if (ResourceHelper.getSymbolicNameAttribute(resource).startsWith(RegionContextBundleHelper.SYMBOLICNAME_PREFIX))
+					continue;
+				try {
+					stopResource(resource);
+				} 
+				catch (Exception e) {
+					logger.error("An error occurred while stopping resource " + resource + " of subsystem " + subsystem, e);
+				}
+			}
+		}
+		// TODO Can we automatically assume it actually is resolved?
+		subsystem.setState(State.RESOLVED);
+		try {
+			subsystem.setDeploymentManifest(new DeploymentManifest(
+					subsystem.getDeploymentManifest(),
+					null,
+					subsystem.isAutostart(),
+					subsystem.getSubsystemId(),
+					SubsystemIdentifier.getLastId(),
+					subsystem.getLocation(),
+					false,
+					false));
+		}
+		catch (Exception e) {
+			throw new SubsystemException(e);
+		}
+		return null;
+	}
+	
+	private void stopBundleResource(Resource resource) throws BundleException {
+		((BundleRevision)resource).getBundle().stop();
+	}
+	
+	private void stopResource(Resource resource) throws BundleException, IOException {
+		if (Utils.getActiveUseCount(resource) >= 1)
+			return;
+		String type = ResourceHelper.getTypeAttribute(resource);
+		if (SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION.equals(type)
+				|| SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE.equals(type)
+				|| SubsystemConstants.SUBSYSTEM_TYPE_FEATURE.equals(type))
+			stopSubsystemResource(resource);
+		else if (IdentityNamespace.TYPE_BUNDLE.equals(type))
+			stopBundleResource(resource);
+		else if (IdentityNamespace.TYPE_FRAGMENT.equals(type))
+			return;
+		else
+			throw new SubsystemException("Unsupported resource type: " + type);
+	}
+	
+	private void stopSubsystemResource(Resource resource) throws IOException {
+		((AriesSubsystem)resource).stop();
+	}
+}

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=1353319&r1=1353318&r2=1353319&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 Jun 24 19:48:40 2012
@@ -47,7 +47,7 @@ public class SubsystemResolverHook imple
 		Collection<BundleCapability> preferredProviders = new ArrayList<BundleCapability>(candidates.size());
 		for (BundleCapability candidate : candidates)
 			for (AriesSubsystem subsystem : requirers) {
-				PreferredProviderHeader header = subsystem.getArchive().getSubsystemManifest().getPreferredProviderHeader();
+				PreferredProviderHeader header = subsystem.getSubsystemManifest().getPreferredProviderHeader();
 				if (header != null && (header.contains(candidate.getResource()) || isResourceConstituentOfPreferredSubsystem(candidate.getResource(), subsystem)))
 					preferredProviders.add(candidate);
 			}
@@ -89,7 +89,7 @@ public class SubsystemResolverHook imple
 	private boolean isResourceConstituentOfPreferredSubsystem(Resource resource, AriesSubsystem preferer) {
 		Collection<AriesSubsystem> subsystems = Activator.getInstance().getSubsystems().getSubsystemsReferencing(resource);
 		for (AriesSubsystem subsystem : subsystems)
-			if (preferer.getArchive().getSubsystemManifest().getPreferredProviderHeader().contains(subsystem))
+			if (preferer.getSubsystemManifest().getPreferredProviderHeader().contains(subsystem))
 				return true;
 		return false;
 	}

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=1353319&r1=1353318&r2=1353319&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 Sun Jun 24 19:48:40 2012
@@ -11,26 +11,51 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.aries.subsystem.core.archive.Attribute;
 import org.apache.aries.subsystem.core.archive.DeployedContentHeader;
 import org.apache.aries.subsystem.core.archive.DeploymentManifest;
+import org.apache.aries.subsystem.core.archive.Header;
+import org.apache.aries.subsystem.core.archive.ImportPackageHeader;
+import org.apache.aries.subsystem.core.archive.ImportPackageRequirement;
 import org.apache.aries.subsystem.core.archive.ProvisionResourceHeader;
+import org.apache.aries.subsystem.core.archive.RequireBundleHeader;
+import org.apache.aries.subsystem.core.archive.RequireBundleRequirement;
+import org.apache.aries.subsystem.core.archive.RequireCapabilityHeader;
+import org.apache.aries.subsystem.core.archive.RequireCapabilityRequirement;
 import org.apache.aries.subsystem.core.archive.SubsystemContentHeader;
+import org.apache.aries.subsystem.core.archive.SubsystemImportServiceHeader;
+import org.apache.aries.subsystem.core.archive.SubsystemImportServiceRequirement;
 import org.apache.aries.subsystem.core.archive.SubsystemManifest;
+import org.apache.aries.util.filesystem.FileSystem;
+import org.apache.aries.util.filesystem.IDirectory;
+import org.eclipse.equinox.region.Region;
+import org.eclipse.equinox.region.RegionDigraph;
+import org.eclipse.equinox.region.RegionFilter;
+import org.eclipse.equinox.region.RegionFilterBuilder;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.namespace.IdentityNamespace;
 import org.osgi.framework.wiring.BundleRevision;
 import org.osgi.resource.Capability;
 import org.osgi.resource.Requirement;
 import org.osgi.resource.Resource;
 import org.osgi.resource.Wire;
 import org.osgi.resource.Wiring;
+import org.osgi.service.coordinator.Coordination;
+import org.osgi.service.coordinator.Participant;
 import org.osgi.service.repository.Repository;
 import org.osgi.service.resolver.HostedCapability;
 import org.osgi.service.resolver.ResolutionException;
 import org.osgi.service.resolver.ResolveContext;
+import org.osgi.service.subsystem.Subsystem;
 import org.osgi.service.subsystem.SubsystemConstants;
 import org.osgi.service.subsystem.SubsystemException;
 
 public class SubsystemResource implements Resource {
+	private Region region;
+	
 	private final DeploymentManifest deploymentManifest;
+	private final long id;
 	private final Collection<Resource> installableContent = new HashSet<Resource>();
 	private final Collection<Resource> installableDependencies = new HashSet<Resource>();
 	private final Collection<Resource> mandatoryResources = new HashSet<Resource>();
@@ -48,11 +73,26 @@ public class SubsystemResource implement
 	public SubsystemResource(RawSubsystemResource resource, AriesSubsystem parent) throws IOException {
 		this.parent = parent;
 		this.resource = resource;
+		id = SubsystemIdentifier.getNextId();
 		preferredProviderRepository = new PreferredProviderRepository(this);
-		computeContentResources();
-		computeDependencies();
+		computeContentResources(resource.getDeploymentManifest());
+		computeDependencies(resource.getDeploymentManifest());
 		deploymentManifest = computeDeploymentManifest();
 	}
+	
+	public SubsystemResource(File file) throws IOException, URISyntaxException, ResolutionException {
+		this(FileSystem.getFSRoot(file));
+	}
+	
+	public SubsystemResource(IDirectory directory) throws IOException, URISyntaxException, ResolutionException {
+		parent = null;
+		resource = new RawSubsystemResource(directory);
+		preferredProviderRepository = null;
+		deploymentManifest = resource.getDeploymentManifest();
+		id = Long.parseLong(deploymentManifest.getHeaders().get(DeploymentManifest.ARIESSUBSYSTEM_ID).getValue());
+		computeContentResources(deploymentManifest);
+		computeDependencies(deploymentManifest);
+	}
 
 	@Override
 	public List<Capability> getCapabilities(String namespace) {
@@ -63,12 +103,8 @@ public class SubsystemResource implement
 		return deploymentManifest;
 	}
 	
-	public File getDirectory() {
-		return resource.getDirectory();
-	}
-	
 	public long getId() {
-		return resource.getId();
+		return id;
 	}
 	
 	public Collection<Resource> getInstallableContent() {
@@ -87,8 +123,38 @@ public class SubsystemResource implement
 		return resource.getLocation().getValue();
 	}
 	
-	public AriesSubsystem getParent() {
-		return parent;
+	public Collection<AriesSubsystem> getParents() {
+		if (parent == null) {
+			Header<?> header = getDeploymentManifest().getHeaders().get(DeploymentManifest.ARIESSUBSYSTEM_PARENTS);
+			if (header == null)
+				return Collections.emptyList();
+			String[] parents = header.getValue().split(",");
+			Collection<AriesSubsystem> result = new ArrayList<AriesSubsystem>(parents.length);
+			for (String parent : parents)
+				result.add(Activator.getInstance().getSubsystems().getSubsystemById(Long.valueOf(parent)));
+			return result;
+		}
+		return Collections.singleton(parent);
+	}
+	
+	public synchronized Region getRegion() throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
+		if (region == null) {
+			region = createRegion(getId());
+			Coordination coordination = Activator.getInstance().getCoordinator().peek();
+			coordination.addParticipant(new Participant() {
+				@Override
+				public void ended(Coordination arg0) throws Exception {
+//					region.getRegionDigraph().removeRegion(region);
+				}
+
+				@Override
+				public void failed(Coordination arg0) throws Exception {
+					region.getRegionDigraph().removeRegion(region);
+				}
+			});
+			setImportIsolationPolicy();
+		}
+		return region;
 	}
 
 	@Override
@@ -125,7 +191,7 @@ public class SubsystemResource implement
 			sharedContent.add(resource);
 	}
 	
-	private boolean addDependencies(Repository repository, Requirement requirement, List<Capability> capabilities) {
+	private boolean addDependencies(Repository repository, Requirement requirement, List<Capability> capabilities) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
 		Map<Requirement, Collection<Capability>> m = repository.findProviders(Collections.singleton(requirement));
 		if (m.containsKey(requirement)) {
 			Collection<Capability> cc = m.get(requirement);
@@ -135,26 +201,26 @@ public class SubsystemResource implement
 		return !capabilities.isEmpty();
 	}
 	
-	private boolean addDependenciesFromContentRepository(Requirement requirement, List<Capability> capabilities) {
+	private boolean addDependenciesFromContentRepository(Requirement requirement, List<Capability> capabilities) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
 		Repository repository = new ContentRepository(installableContent, sharedContent);
 		return addDependencies(repository, requirement, capabilities);
 	}
 	
-	private boolean addDependenciesFromLocalRepository(Requirement requirement, List<Capability> capabilities) {
+	private boolean addDependenciesFromLocalRepository(Requirement requirement, List<Capability> capabilities) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
 		Repository repository = resource.getLocalRepository();
 		return addDependencies(repository, requirement, capabilities);
 	}
 	
-	private boolean addDependenciesFromPreferredProviderRepository(Requirement requirement, List<Capability> capabilities) {
+	private boolean addDependenciesFromPreferredProviderRepository(Requirement requirement, List<Capability> capabilities) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
 		return addDependencies(preferredProviderRepository, requirement, capabilities);
 	}
 	
-	private boolean addDependenciesFromRepositoryServiceRepositories(Requirement requirement, List<Capability> capabilities) {
+	private boolean addDependenciesFromRepositoryServiceRepositories(Requirement requirement, List<Capability> capabilities) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
 		Repository repository = new RepositoryServiceRepository();
 		return addDependencies(repository, requirement, capabilities);
 	}
 	
-	private boolean addDependenciesFromSystemRepository(Requirement requirement, List<Capability> capabilities) {
+	private boolean addDependenciesFromSystemRepository(Requirement requirement, List<Capability> capabilities) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
 		Repository repository = Activator.getInstance().getSystemRepository();
 		return addDependencies(repository, requirement, capabilities);
 	}
@@ -168,14 +234,64 @@ public class SubsystemResource implement
 			sharedDependencies.add(resource);
 	}
 	
-	private void addValidCapabilities(Collection<Capability> from, Collection<Capability> to) {
+	private void addValidCapabilities(Collection<Capability> from, Collection<Capability> to) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
 		for (Capability c : from)
 			if (isValid(c))
 				to.add(c);
 	}
 	
-	private void computeContentResources() {
-		SubsystemContentHeader contentHeader = resource.getSubsystemManifest().getSubsystemContentHeader();
+	private void addSubsystemServiceImportToSharingPolicy(
+			RegionFilterBuilder builder) throws InvalidSyntaxException, BundleException, IOException, URISyntaxException {
+		builder.allow(
+				RegionFilter.VISIBLE_SERVICE_NAMESPACE,
+				new StringBuilder("(&(")
+						.append(org.osgi.framework.Constants.OBJECTCLASS)
+						.append('=').append(Subsystem.class.getName())
+						.append(")(")
+						.append(Constants.SubsystemServicePropertyRegions)
+						.append('=').append(getRegion().getName())
+						.append("))").toString());
+	}
+	
+	private void addSubsystemServiceImportToSharingPolicy(RegionFilterBuilder builder, Region to)
+			throws InvalidSyntaxException, BundleException, IOException, URISyntaxException {
+		if (to.getName().equals(AriesSubsystem.ROOT_REGION))
+			addSubsystemServiceImportToSharingPolicy(builder);
+		else {
+			to = Activator.getInstance().getSubsystems().getRootSubsystem().getRegion();
+			builder = to.getRegionDigraph().createRegionFilterBuilder();
+			addSubsystemServiceImportToSharingPolicy(builder);
+			RegionFilter regionFilter = builder.build();
+			getRegion().connectRegion(to, regionFilter);
+		}
+	}
+	
+	private void computeContentResources(DeploymentManifest manifest) {
+		if (manifest == null)
+			computeContentResources(getSubsystemManifest());
+		else {
+			DeployedContentHeader header = manifest.getDeployedContentHeader();
+			if (header == null)
+				return;
+			for (DeployedContentHeader.Clause clause : header.getClauses()) {
+				Resource resource = findContent(clause);
+				if (resource == null)
+					throw new SubsystemException("Resource does not exist: " + clause);
+				addContentResource(resource);
+			}
+		}
+//		if (parent == null) {
+//			if (deploymentManifest == null)
+//				return;
+//			computeContentResourcesFromDeploymentManifest();
+//		}
+//		else {
+//			computeContentResourcesFromSubsystemManifest();
+//		}
+	}
+	
+	private void computeContentResources(SubsystemManifest manifest) {
+		SubsystemContentHeader contentHeader = manifest.getSubsystemContentHeader();
 		if (contentHeader == null)
 			return;
 		for (SubsystemContentHeader.Content content : contentHeader.getContents()) {
@@ -192,8 +308,49 @@ public class SubsystemResource implement
 		}
 	}
 	
-	private void computeDependencies() {
-		SubsystemContentHeader contentHeader = resource.getSubsystemManifest().getSubsystemContentHeader();
+	private void computeDependencies(DeploymentManifest manifest) {
+		if (manifest == null)
+			computeDependencies(getSubsystemManifest());
+		else {
+			ProvisionResourceHeader header = manifest.getProvisionResourceHeader();
+			if (header == null)
+				return;
+			for (ProvisionResourceHeader.ProvisionedResource provisionedResource : header.getProvisionedResources()) {
+				Resource resource = findDependency(provisionedResource);
+				if (resource == null)
+					throw new SubsystemException("Resource does not exist: " + provisionedResource);
+				addDependency(resource);
+			}
+		}	
+//		if (parent == null) {
+//			if (deploymentManifest == null)
+//				return;
+//			ProvisionResourceHeader header = deploymentManifest.getProvisionResourceHeader();
+//			if (header == null)
+//				return;
+//			for (ProvisionResourceHeader.ProvisionedResource provisionedResource : header.getProvisionedResources()) {
+//				Resource resource = findDependency(provisionedResource);
+//				if (resource == null)
+//					throw new SubsystemException("Resource does not exist: " + provisionedResource);
+//				addContentResource(resource);
+//			}
+//		}
+//		else {
+//			SubsystemContentHeader contentHeader = resource.getSubsystemManifest().getSubsystemContentHeader();
+//			try {
+//				Map<Resource, List<Wire>> resolution = Activator.getInstance().getResolver().resolve(createResolveContext());
+//				for (Resource resource : resolution.keySet())
+//					if (!contentHeader.contains(resource))
+//						addDependency(resource);
+//			}
+//			catch (ResolutionException e) {
+//				throw new SubsystemException(e);
+//			}
+//		}
+	}
+	
+	private void computeDependencies(SubsystemManifest manifest) {
+		SubsystemContentHeader contentHeader = manifest.getSubsystemContentHeader();
 		try {
 			Map<Resource, List<Wire>> resolution = Activator.getInstance().getResolver().resolve(createResolveContext());
 			for (Resource resource : resolution.keySet())
@@ -233,21 +390,53 @@ public class SubsystemResource implement
 		return ProvisionResourceHeader.newInstance(dependencies);
 	}
 	
+	private Region createRegion(long id) throws BundleException {
+		if (!isScoped())
+			return getParents().iterator().next().getRegion();
+		Activator activator = Activator.getInstance();
+		RegionDigraph digraph = activator.getRegionDigraph();
+		if (getParents().isEmpty())
+			return digraph.getRegion(AriesSubsystem.ROOT_REGION);
+		String name = getSubsystemManifest()
+				.getSubsystemSymbolicNameHeader().getSymbolicName()
+				+ ';'
+				+ getSubsystemManifest().getSubsystemVersionHeader()
+						.getVersion()
+				+ ';'
+				+ getSubsystemManifest().getSubsystemTypeHeader()
+						.getType() + ';' + Long.toString(id);
+		Region region = digraph.getRegion(name);
+		// TODO New regions need to be cleaned up if this subsystem fails to
+		// install, but there's no access to the coordination here.
+		if (region == null)
+			return digraph.createRegion(name);
+		return region;
+	}
+	
 	private ResolveContext createResolveContext() {
 		return new ResolveContext() {
 			@Override
 			public List<Capability> findProviders(Requirement requirement) {
 				List<Capability> result = new ArrayList<Capability>();
-				if (addDependenciesFromContentRepository(requirement, result))
-					return result;
-				if (addDependenciesFromPreferredProviderRepository(requirement, result))
-					return result;
-				if (addDependenciesFromSystemRepository(requirement, result))
-					return result;
-				if (addDependenciesFromLocalRepository(requirement, result))
-					return result;
-				if (addDependenciesFromRepositoryServiceRepositories(requirement, result))
-					return result;
+				try {
+					if (addDependenciesFromContentRepository(requirement, result))
+						return result;
+					if (addDependenciesFromPreferredProviderRepository(requirement, result))
+						return result;
+					if (addDependenciesFromSystemRepository(requirement, result))
+						return result;
+					if (addDependenciesFromLocalRepository(requirement, result))
+						return result;
+					if (addDependenciesFromRepositoryServiceRepositories(requirement, result))
+						return result;
+				}
+				catch (Throwable t) {
+					if (t instanceof SubsystemException)
+						throw (SubsystemException)t;
+					if (t instanceof SecurityException)
+						throw (SecurityException)t;
+					throw new SubsystemException(t);
+				}
 				return result;
 			}
 			
@@ -308,6 +497,41 @@ public class SubsystemResource implement
 		return null;
 	}
 	
+	private Resource findContent(DeployedContentHeader.Clause clause) {
+		Attribute attribute = clause.getAttribute(DeployedContentHeader.Clause.ATTRIBUTE_RESOURCEID);
+		long resourceId = attribute == null ? -1 : Long.parseLong(String.valueOf(attribute.getValue()));
+		if (resourceId != -1) {
+			String type = clause.getType();
+			if (IdentityNamespace.TYPE_BUNDLE.equals(type) || IdentityNamespace.TYPE_FRAGMENT.equals(type)) {
+				return Activator.getInstance().getBundleContext().getBundle(0).getBundleContext().getBundle(resourceId).adapt(BundleRevision.class);
+			}
+			else
+				return Activator.getInstance().getSubsystems().getSubsystemById(resourceId);
+		}
+		OsgiIdentityRequirement requirement = new OsgiIdentityRequirement(
+				clause.getPath(), clause.getDeployedVersion(),
+				clause.getType(), false);
+		return findContent(requirement);
+	}
+	
+	private Resource findDependency(ProvisionResourceHeader.ProvisionedResource provisionedResource) {
+		long resourceId = provisionedResource.getResourceId();
+		if (resourceId != -1) {
+			String type = provisionedResource.getNamespace();
+			if (IdentityNamespace.TYPE_BUNDLE.equals(type) || IdentityNamespace.TYPE_FRAGMENT.equals(type))
+				return Activator.getInstance().getBundleContext().getBundle(0).getBundleContext().getBundle(resourceId).adapt(BundleRevision.class);
+			else
+				return Activator.getInstance().getSubsystems().getSubsystemById(resourceId);
+		}
+		OsgiIdentityRequirement requirement = new OsgiIdentityRequirement(
+				provisionedResource.getName(), provisionedResource.getDeployedVersion(),
+				provisionedResource.getNamespace(), false);
+		List<Capability> capabilities = createResolveContext().findProviders(requirement);
+		if (capabilities.isEmpty())
+			return null;
+		return capabilities.get(0).getResource();
+	}
+	
 	private Collection<Resource> getContentResources() {
 		Collection<Resource> result = new ArrayList<Resource>(installableContent.size() + sharedContent.size());
 		result.addAll(installableContent);
@@ -322,6 +546,10 @@ public class SubsystemResource implement
 		return result;
 	}
 	
+	private boolean isContent(Resource resource) {
+		return getSubsystemManifest().getSubsystemContentHeader().contains(resource);
+	}
+	
 	private boolean isInstallable(Resource resource) {
 		return !isShared(resource);
 	}
@@ -333,8 +561,12 @@ public class SubsystemResource implement
 		return header.isMandatory(resource);
 	}
 	
+	private boolean isRoot() {
+		return AriesSubsystem.ROOT_LOCATION.equals(getLocation());
+	}
+	
 	private boolean isShared(Resource resource) {
-		return resource instanceof AriesSubsystem || resource instanceof BundleRevision;
+		return Utils.isSharedResource(resource);
 	}
 	
 	private boolean isScoped() {
@@ -347,12 +579,91 @@ public class SubsystemResource implement
 		return !isScoped();
 	}
 	
-	private boolean isValid(Capability capability) {
-		AriesSubsystem subsystem;
-		if (isInstallable(capability.getResource()))
-			subsystem = Utils.findFirstSubsystemAcceptingDependenciesStartingFrom(parent);
+	private boolean isValid(Capability capability) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
+		if (IdentityNamespace.IDENTITY_NAMESPACE.equals(capability.getNamespace()))
+			return true;
+		Region region;
+		if (isInstallable(capability.getResource())) {
+			if (isContent(capability.getResource()))
+				region = getRegion();
+			else
+				region = Utils.findFirstSubsystemAcceptingDependenciesStartingFrom(parent).getRegion();
+		}
 		else
-			subsystem = Activator.getInstance().getSubsystems().getSubsystemsReferencing(capability.getResource()).iterator().next();
-		return new SharingPolicyValidator(subsystem.getRegion(), parent.getRegion()).isValid(capability);
+			region = Activator.getInstance().getSubsystems().getSubsystemsReferencing(capability.getResource()).iterator().next().getRegion();
+		return new SharingPolicyValidator(region, getRegion()).isValid(capability);
+	}
+	
+	private void setImportIsolationPolicy() throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
+		if (isRoot() || !isScoped())
+			return;
+		Region region = getRegion();
+		Region from = region;
+		RegionFilterBuilder builder = from.getRegionDigraph().createRegionFilterBuilder();
+		Region to = ((AriesSubsystem)getParents().iterator().next()).getRegion();
+		addSubsystemServiceImportToSharingPolicy(builder, to);
+		// TODO Is this check really necessary? Looks like it was done at the beginning of this method.
+		if (isScoped()) {
+			// Both applications and composites have Import-Package headers that require processing.
+			// In the case of applications, the header is generated.
+			Header<?> header = getSubsystemManifest().getImportPackageHeader();
+			setImportIsolationPolicy(builder, (ImportPackageHeader)header);
+			// Both applications and composites have Require-Capability headers that require processing.
+			// In the case of applications, the header is generated.
+			header = getSubsystemManifest().getRequireCapabilityHeader();
+			setImportIsolationPolicy(builder, (RequireCapabilityHeader)header);
+			// Both applications and composites have Subsystem-ImportService headers that require processing.
+			// In the case of applications, the header is generated.
+			header = getSubsystemManifest().getSubsystemImportServiceHeader();
+			setImportIsolationPolicy(builder, (SubsystemImportServiceHeader)header);
+			header = getSubsystemManifest().getRequireBundleHeader();
+			setImportIsolationPolicy(builder, (RequireBundleHeader)header);
+		}
+		RegionFilter regionFilter = builder.build();
+		from.connectRegion(to, regionFilter);
+	}
+	
+	private void setImportIsolationPolicy(RegionFilterBuilder builder, ImportPackageHeader header) throws InvalidSyntaxException {
+		if (header == null)
+			return;
+		String policy = RegionFilter.VISIBLE_PACKAGE_NAMESPACE;
+		for (ImportPackageHeader.Clause clause : header.getClauses()) {
+			ImportPackageRequirement requirement = new ImportPackageRequirement(clause, this);
+			String filter = requirement.getDirectives().get(ImportPackageRequirement.DIRECTIVE_FILTER);
+			builder.allow(policy, filter);
+		}
+	}
+	
+	private void setImportIsolationPolicy(RegionFilterBuilder builder, RequireBundleHeader header) throws InvalidSyntaxException {
+		if (header == null)
+			return;
+		for (RequireBundleHeader.Clause clause : header.getClauses()) {
+			RequireBundleRequirement requirement = new RequireBundleRequirement(clause, this);
+			String policy = RegionFilter.VISIBLE_REQUIRE_NAMESPACE;
+			String filter = requirement.getDirectives().get(RequireBundleRequirement.DIRECTIVE_FILTER);
+			builder.allow(policy, filter);
+		}
+	}
+	
+	private void setImportIsolationPolicy(RegionFilterBuilder builder, RequireCapabilityHeader header) throws InvalidSyntaxException {
+		if (header == null)
+			return;
+		for (RequireCapabilityHeader.Clause clause : header.getClauses()) {
+			RequireCapabilityRequirement requirement = new RequireCapabilityRequirement(clause, this);
+			String policy = requirement.getNamespace();
+			String filter = requirement.getDirectives().get(RequireCapabilityRequirement.DIRECTIVE_FILTER);
+			builder.allow(policy, filter);
+		}
+	}
+	
+	private void setImportIsolationPolicy(RegionFilterBuilder builder, SubsystemImportServiceHeader header) throws InvalidSyntaxException {
+		if (header == null)
+			return;
+		for (SubsystemImportServiceHeader.Clause clause : header.getClauses()) {
+			SubsystemImportServiceRequirement requirement = new SubsystemImportServiceRequirement(clause, this);
+			String policy = RegionFilter.VISIBLE_SERVICE_NAMESPACE;
+			String filter = requirement.getDirectives().get(SubsystemImportServiceRequirement.DIRECTIVE_FILTER);
+			builder.allow(policy, filter);
+		}
 	}
 }

Modified: 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=1353319&r1=1353318&r2=1353319&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResourceInstaller.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResourceInstaller.java Sun Jun 24 19:48:40 2012
@@ -1,36 +1,36 @@
 package org.apache.aries.subsystem.core.internal;
 
 import java.security.AccessController;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
 
 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.Subsystem.State;
 
 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;
-		}
+	public Resource install() throws Exception {
+		if (resource instanceof RepositoryContent)
+			return installRepositoryContent((RepositoryContent)resource);
 		else if (resource instanceof AriesSubsystem)
-			subsystem = (AriesSubsystem)resource;
+			return installAriesSubsystem((AriesSubsystem)resource);
 		else if (resource instanceof RawSubsystemResource)
-			subsystem = new AriesSubsystem(new SubsystemResource((RawSubsystemResource)resource, provisionTo), provisionTo);
+			return installRawSubsystemResource((RawSubsystemResource)resource);
 		else
-			subsystem = new AriesSubsystem((SubsystemResource)resource, provisionTo);
-		addChild(subsystem);
-		addConstituent(subsystem);
-		addReference(subsystem);
-		subsystem.install(coordination, provisionTo);
+			return installSubsystemResource((SubsystemResource)resource);
 	}
 	
 	private void addChild(final AriesSubsystem child) {
+		if (provisionTo == null || subsystem == null)
+			return;
 		Activator.getInstance().getSubsystems().addChild(subsystem, child);
 		coordination.addParticipant(new Participant() {
 			@Override
@@ -44,4 +44,173 @@ public class SubsystemResourceInstaller 
 			}
 		});
 	}
+	
+	private void addSubsystem(final AriesSubsystem subsystem) {
+		Activator.getInstance().getSubsystems().addSubsystem(subsystem);
+		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(subsystem);
+			}
+		});
+	}
+	
+//	private void addSubsystemServiceImportToSharingPolicy(
+//			RegionFilterBuilder builder, AriesSubsystem subsystem) throws InvalidSyntaxException {
+//		builder.allow(
+//				RegionFilter.VISIBLE_SERVICE_NAMESPACE,
+//				new StringBuilder("(&(")
+//						.append(org.osgi.framework.Constants.OBJECTCLASS)
+//						.append('=').append(Subsystem.class.getName())
+//						.append(")(")
+//						.append(Constants.SubsystemServicePropertyRegions)
+//						.append('=').append(subsystem.getRegion().getName())
+//						.append("))").toString());
+//	}
+	
+//	private void addSubsystemServiceImportToSharingPolicy(RegionFilterBuilder builder, Region to, AriesSubsystem subsystem)
+//			throws InvalidSyntaxException, BundleException {
+//		if (to.getName().equals(AriesSubsystem.ROOT_REGION))
+//			addSubsystemServiceImportToSharingPolicy(builder, subsystem);
+//		else {
+//			to = Activator.getInstance().getSubsystems().getRootSubsystem().getRegion();
+//			builder = to.getRegionDigraph().createRegionFilterBuilder();
+//			addSubsystemServiceImportToSharingPolicy(builder, subsystem);
+//			RegionFilter regionFilter = builder.build();
+//			subsystem.getRegion().connectRegion(to, regionFilter);
+//		}
+//	}
+	
+	private Resource installAriesSubsystem(AriesSubsystem subsystem) throws Exception {
+		addChild(subsystem);
+		addConstituent(subsystem);
+		addReference(subsystem);
+		// TODO Is this check really necessary?
+		if (!State.INSTALLING.equals(subsystem.getState()))
+			return subsystem;
+		addSubsystem(subsystem);
+		if (subsystem.isScoped())
+			RegionContextBundleHelper.installRegionContextBundle(subsystem);
+		Activator.getInstance().getSubsystemServiceRegistrar().register(subsystem, this.subsystem);
+		// 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(subsystem);
+		if (!subsystem.isRoot()) {
+			Comparator<Resource> comparator = new InstallResourceComparator();
+			// Install dependencies first...
+			List<Resource> dependencies = new ArrayList<Resource>(subsystem.getResource().getInstallableDependencies());
+			Collections.sort(dependencies, comparator);
+			for (Resource dependency : dependencies)
+				ResourceInstaller.newInstance(coordination, dependency, subsystem, true).install();
+			for (Resource dependency : subsystem.getResource().getSharedDependencies())
+				ResourceInstaller.newInstance(coordination, dependency, subsystem, true).install();
+			// ...followed by content.
+			List<Resource> installableContent = new ArrayList<Resource>(subsystem.getResource().getInstallableContent());
+			Collections.sort(installableContent, comparator);
+			for (Resource content : installableContent)
+				ResourceInstaller.newInstance(coordination, content, subsystem, false).install();
+			// Simulate installation of shared content so that necessary relationships are established.
+			for (Resource content : subsystem.getResource().getSharedContent())
+				ResourceInstaller.newInstance(coordination, content, subsystem, false).install();
+		}
+		subsystem.setState(State.INSTALLED);
+		return subsystem;
+	}
+	
+	private Resource installRawSubsystemResource(RawSubsystemResource resource) throws Exception {
+		SubsystemResource subsystemResource = new SubsystemResource(resource, provisionTo);
+		return installSubsystemResource(subsystemResource);
+	}
+	
+	private Resource installRepositoryContent(RepositoryContent resource) {
+		return AccessController.doPrivileged(new InstallAction(getLocation(), resource.getContent(), provisionTo, null, coordination, true));
+	}
+	
+	private Resource installSubsystemResource(SubsystemResource resource) throws Exception {
+		AriesSubsystem subsystem = new AriesSubsystem(resource);
+		installAriesSubsystem(subsystem);
+		if (subsystem.isAutostart())
+			subsystem.start();
+		return subsystem;
+	}
+	
+//	private void setImportIsolationPolicy(AriesSubsystem subsystem) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
+//		if (subsystem.isRoot() || !subsystem.isScoped())
+//			return;
+//		Region region = subsystem.getRegion();
+//		Region from = region;
+//		RegionFilterBuilder builder = from.getRegionDigraph().createRegionFilterBuilder();
+//		Region to = ((AriesSubsystem)subsystem.getParents().iterator().next()).getRegion();
+//		addSubsystemServiceImportToSharingPolicy(builder, to, subsystem);
+//		// TODO Is this check really necessary? Looks like it was done at the beginning of this method.
+//		if (subsystem.isScoped()) {
+//			// Both applications and composites have Import-Package headers that require processing.
+//			// In the case of applications, the header is generated.
+//			Header<?> header = subsystem.getSubsystemManifest().getImportPackageHeader();
+//			setImportIsolationPolicy(builder, (ImportPackageHeader)header, subsystem);
+//			// Both applications and composites have Require-Capability headers that require processing.
+//			// In the case of applications, the header is generated.
+//			header = subsystem.getSubsystemManifest().getRequireCapabilityHeader();
+//			setImportIsolationPolicy(builder, (RequireCapabilityHeader)header, subsystem);
+//			// Both applications and composites have Subsystem-ImportService headers that require processing.
+//			// In the case of applications, the header is generated.
+//			header = subsystem.getSubsystemManifest().getSubsystemImportServiceHeader();
+//			setImportIsolationPolicy(builder, (SubsystemImportServiceHeader)header, subsystem);
+//			header = subsystem.getSubsystemManifest().getRequireBundleHeader();
+//			setImportIsolationPolicy(builder, (RequireBundleHeader)header, subsystem);
+//		}
+//		RegionFilter regionFilter = builder.build();
+//		from.connectRegion(to, regionFilter);
+//	}
+//	
+//	private void setImportIsolationPolicy(RegionFilterBuilder builder, ImportPackageHeader header, AriesSubsystem subsystem) throws InvalidSyntaxException {
+//		if (header == null)
+//			return;
+//		String policy = RegionFilter.VISIBLE_PACKAGE_NAMESPACE;
+//		for (ImportPackageHeader.Clause clause : header.getClauses()) {
+//			ImportPackageRequirement requirement = new ImportPackageRequirement(clause, subsystem);
+//			String filter = requirement.getDirectives().get(ImportPackageRequirement.DIRECTIVE_FILTER);
+//			builder.allow(policy, filter);
+//		}
+//	}
+//	
+//	private void setImportIsolationPolicy(RegionFilterBuilder builder, RequireBundleHeader header, AriesSubsystem subsystem) throws InvalidSyntaxException {
+//		if (header == null)
+//			return;
+//		for (RequireBundleHeader.Clause clause : header.getClauses()) {
+//			RequireBundleRequirement requirement = new RequireBundleRequirement(clause, subsystem);
+//			String policy = RegionFilter.VISIBLE_REQUIRE_NAMESPACE;
+//			String filter = requirement.getDirectives().get(RequireBundleRequirement.DIRECTIVE_FILTER);
+//			builder.allow(policy, filter);
+//		}
+//	}
+//	
+//	private void setImportIsolationPolicy(RegionFilterBuilder builder, RequireCapabilityHeader header, AriesSubsystem subsystem) throws InvalidSyntaxException {
+//		if (header == null)
+//			return;
+//		for (RequireCapabilityHeader.Clause clause : header.getClauses()) {
+//			RequireCapabilityRequirement requirement = new RequireCapabilityRequirement(clause, subsystem);
+//			String policy = requirement.getNamespace();
+//			String filter = requirement.getDirectives().get(RequireCapabilityRequirement.DIRECTIVE_FILTER);
+//			builder.allow(policy, filter);
+//		}
+//	}
+//	
+//	private void setImportIsolationPolicy(RegionFilterBuilder builder, SubsystemImportServiceHeader header, AriesSubsystem subsystem) throws InvalidSyntaxException {
+//		if (header == null)
+//			return;
+//		for (SubsystemImportServiceHeader.Clause clause : header.getClauses()) {
+//			SubsystemImportServiceRequirement requirement = new SubsystemImportServiceRequirement(clause, subsystem);
+//			String policy = RegionFilter.VISIBLE_SERVICE_NAMESPACE;
+//			String filter = requirement.getDirectives().get(SubsystemImportServiceRequirement.DIRECTIVE_FILTER);
+//			builder.allow(policy, filter);
+//		}
+//	}
 }

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResourceUninstaller.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResourceUninstaller.java?rev=1353319&r1=1353318&r2=1353319&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResourceUninstaller.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResourceUninstaller.java Sun Jun 24 19:48:40 2012
@@ -25,6 +25,7 @@ public class SubsystemResourceUninstalle
 		removeReferences();
 		removeConstituents();
 		removeChildren();
+		removeSubsystem();
 	}
 	
 	private void removeChildren() {
@@ -54,31 +55,39 @@ public class SubsystemResourceUninstalle
 			removeReference((AriesSubsystem)subsystem, (AriesSubsystem)resource);
 	}
 	
+	private void removeSubsystem() {
+		Activator.getInstance().getSubsystems().removeSubsystem((AriesSubsystem)resource);
+	}
+	
 	private void uninstallSubsystem() {
-		AriesSubsystem subsystem = (AriesSubsystem)resource;
+		AriesSubsystem subsystem = (AriesSubsystem) resource;
 		if (subsystem.getState().equals(Subsystem.State.RESOLVED))
-				subsystem.setState(State.INSTALLED);
-			subsystem.setState(State.UNINSTALLING);
-			Throwable firstError = null;
-			for (Resource resource : Activator.getInstance().getSubsystems().getResourcesReferencedBy(subsystem)) {
-				// Don't uninstall the region context bundle here.
-				if (ResourceHelper.getSymbolicNameAttribute(resource).startsWith(RegionContextBundleHelper.SYMBOLICNAME_PREFIX))
-					continue;
-				try {
-					ResourceUninstaller.newInstance(resource, subsystem).uninstall();
-				}
-				catch (Throwable t) {
-					logger.error("An error occurred while uninstalling resource " + resource + " of subsystem " + subsystem, t);
-					if (firstError == null)
-						firstError = t;
-				}
+			subsystem.setState(State.INSTALLED);
+		subsystem.setState(State.UNINSTALLING);
+		Throwable firstError = null;
+		for (Resource resource : Activator.getInstance().getSubsystems()
+				.getResourcesReferencedBy(subsystem)) {
+			// Don't uninstall the region context bundle here.
+			if (ResourceHelper.getSymbolicNameAttribute(resource).startsWith(
+					RegionContextBundleHelper.SYMBOLICNAME_PREFIX))
+				continue;
+			try {
+				ResourceUninstaller.newInstance(resource, subsystem)
+						.uninstall();
+			} catch (Throwable t) {
+				logger.error("An error occurred while uninstalling resource "
+						+ resource + " of subsystem " + subsystem, t);
+				if (firstError == null)
+					firstError = t;
 			}
-			IOUtils.deleteRecursive(subsystem.getDirectory());
-			subsystem.setState(State.UNINSTALLED);
-			Activator.getInstance().getSubsystemServiceRegistrar().unregister(subsystem);
-			if (subsystem.isScoped())
-				RegionContextBundleHelper.uninstallRegionContextBundle(subsystem);
-			if (firstError != null)
-				throw new SubsystemException(firstError);
+		}
+		subsystem.setState(State.UNINSTALLED);
+		Activator.getInstance().getSubsystemServiceRegistrar()
+				.unregister(subsystem);
+		if (subsystem.isScoped())
+			RegionContextBundleHelper.uninstallRegionContextBundle(subsystem);
+		if (firstError != null)
+			throw new SubsystemException(firstError);
+		IOUtils.deleteRecursive(subsystem.getDirectory());
 	}
 }
\ No newline at end of file

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemServiceRegistrar.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemServiceRegistrar.java?rev=1353319&r1=1353318&r2=1353319&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemServiceRegistrar.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemServiceRegistrar.java Sun Jun 24 19:48:40 2012
@@ -43,7 +43,7 @@ public class SubsystemServiceRegistrar {
 	
 	public synchronized void register(AriesSubsystem child, AriesSubsystem parent) {
 		if (map.containsKey(child))
-			throw new IllegalStateException("Subsystem '" + child + "' already has service registration '" + map.get(child) + "'");
+			return;
 		Dictionary<String, Object> properties = properties(child, parent);
 		ServiceRegistration<Subsystem> registration = context.registerService(Subsystem.class, child, properties);
 		map.put(child, registration);

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Subsystems.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Subsystems.java?rev=1353319&r1=1353318&r2=1353319&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Subsystems.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Subsystems.java Sun Jun 24 19:48:40 2012
@@ -1,31 +1,36 @@
 package org.apache.aries.subsystem.core.internal;
 
+import java.io.File;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.wiring.BundleRevision;
 import org.osgi.resource.Resource;
+import org.osgi.service.coordinator.Coordination;
 import org.osgi.service.subsystem.Subsystem;
+import org.osgi.service.subsystem.SubsystemException;
 
 public class Subsystems {
-	private final SubsystemGraph graph;
+	private AriesSubsystem root;
+	private volatile SubsystemGraph graph;
+	
 	private final Map<Long, AriesSubsystem> idToSubsystem = new HashMap<Long, AriesSubsystem>();
 	private final Map<String, AriesSubsystem> locationToSubsystem = new HashMap<String, AriesSubsystem>();
 	private final ResourceReferences resourceReferences = new ResourceReferences();
-	private final AriesSubsystem root;
 	private final Map<AriesSubsystem, Set<Resource>> subsystemToConstituents = new HashMap<AriesSubsystem, Set<Resource>>();
 	
-	public Subsystems() throws Exception {
-		root = new AriesSubsystem();
-		graph = new SubsystemGraph(root);
-	}
-	
 	public void addChild(AriesSubsystem parent, AriesSubsystem child) {
 		graph.add(parent, child);
+		child.addedParent(parent);
 	}
 	
 	public void addConstituent(AriesSubsystem subsystem, Resource constituent) {
@@ -35,9 +40,9 @@ public class Subsystems {
 				constituents = new HashSet<Resource>();
 				subsystemToConstituents.put(subsystem, constituents);
 			}
-			if (!constituents.add(constituent))
-				throw new IllegalArgumentException("Constituent already exists");
+			constituents.add(constituent);
 		}
+		subsystem.addedContent(constituent);
 	}
 	
 	public void addReference(AriesSubsystem subsystem, Resource resource) {
@@ -62,7 +67,7 @@ public class Subsystems {
 			Collection<Resource> result = subsystemToConstituents.get(subsystem);
 			if (result == null)
 				return Collections.emptyList();
-			return Collections.unmodifiableCollection(result);
+			return Collections.unmodifiableCollection(new ArrayList<Resource>(result));
 		}
 	}
 	
@@ -74,7 +79,83 @@ public class Subsystems {
 		return resourceReferences.getResources(subsystem);
 	}
 	
-	public AriesSubsystem getRootSubsystem() {
+	public synchronized AriesSubsystem getRootSubsystem() {
+		if (root == null) {
+			File file = Activator.getInstance().getBundleContext().getDataFile("");
+			File[] fileArray = file.listFiles();
+			List<File> fileList = new ArrayList<File>(Arrays.asList(fileArray));
+			Collections.sort(fileList, new Comparator<File>() {
+				@Override
+				public int compare(File file1, File file2) {
+					String name1 = file1.getName();
+					String name2 = file2.getName();
+					return Long.valueOf(name1).compareTo(Long.valueOf(name2));
+				}
+			});
+			if (fileList.isEmpty()) {
+				SubsystemResource resource;
+				try {
+					resource = new SubsystemResource(file);
+				}
+				catch (SubsystemException e) {
+					throw e;
+				}
+				catch (Exception e) {
+					throw new SubsystemException(e);
+				}
+				Coordination coordination = Utils.createCoordination();
+				try {
+					root = (AriesSubsystem)ResourceInstaller.newInstance(coordination, resource, null, false).install();
+					// 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().getBundle(0).getBundleContext();
+					for (long id : root.getRegion().getBundleIds()) {
+						BundleRevision br = context.getBundle(id).adapt(BundleRevision.class);
+						ResourceInstaller.newInstance(coordination, br, root, false).install();
+					}
+					// TODO End proof of concept.
+				} catch (Exception e) {
+					coordination.fail(e);
+				} finally {
+					coordination.end();
+				}
+				// TODO This initialization is a bit brittle. The root subsystem
+				// must be gotten before anything else will be able to use the
+				// graph. At the very least, throw IllegalStateException where
+				// appropriate.
+				graph = new SubsystemGraph(root);
+			}
+			else {
+				Coordination coordination = Utils.createCoordination();
+				Collection<AriesSubsystem> subsystems = new ArrayList<AriesSubsystem>(fileList.size());
+				try {
+					for (File f : fileList) {
+						AriesSubsystem s = new AriesSubsystem(f);
+						subsystems.add(s);
+						addSubsystem(s);
+					}
+					root = getSubsystemById(0);
+					graph = new SubsystemGraph(root);
+					for (AriesSubsystem s : subsystems) {
+						Collection<Subsystem> parents = s.getParents();
+						if (parents == null || parents.isEmpty()) {
+							ResourceInstaller.newInstance(coordination, s, null, false).install();
+						}
+						else {
+							for (Subsystem parent : s.getParents())
+								ResourceInstaller.newInstance(coordination, s, (AriesSubsystem)parent, false).install();
+						}	
+					}
+				} catch (Exception e) {
+					coordination.fail(e);
+				} finally {
+					coordination.end();
+				}
+			}
+		}
 		return root;
 	}
 	
@@ -98,7 +179,7 @@ public class Subsystems {
 		ArrayList<AriesSubsystem> result = new ArrayList<AriesSubsystem>();
 		synchronized (subsystemToConstituents) {
 			for (AriesSubsystem subsystem : subsystemToConstituents.keySet())
-				if (subsystem.contains(constituent))
+				if (getConstituents(subsystem).contains(constituent))
 					result.add(subsystem);
 		}
 		result.trimToSize();
@@ -120,9 +201,9 @@ public class Subsystems {
 	public void removeConstituent(AriesSubsystem subsystem, Resource constituent) {
 		synchronized (subsystemToConstituents) {
 			Set<Resource> constituents = subsystemToConstituents.get(subsystem);
-			if (!constituents.remove(constituent))
-				throw new IllegalArgumentException("Constituent does not exist");
+			constituents.remove(constituent);
 		}
+		subsystem.removedContent(constituent);
 	}
 	
 	public void removeReference(AriesSubsystem subsystem, Resource resource) {
@@ -140,27 +221,21 @@ public class Subsystems {
 	
 	private void addIdToSubsystem(AriesSubsystem subsystem) {
 		long id = subsystem.getSubsystemId();
-		if (idToSubsystem.containsKey(id))
-			throw new IllegalArgumentException("Subsystem ID already exists: " + id);
 		idToSubsystem.put(id, subsystem);
 	}
 	
 	private void addLocationToSubsystem(AriesSubsystem subsystem) {
 		String location = subsystem.getLocation();
-		if (locationToSubsystem.containsKey(location))
-			throw new IllegalArgumentException("Subsystem location already exists: " + location);
 		locationToSubsystem.put(location, subsystem);
 	}
 	
 	private void removeIdToSubsystem(AriesSubsystem subsystem) {
 		long id = subsystem.getSubsystemId();
-		if (idToSubsystem.remove(id) == null)
-			throw new IllegalArgumentException("Subsystem ID does not exist: " + id);
+		idToSubsystem.remove(id);
 	}
 	
 	private void removeLocationToSubsystem(AriesSubsystem subsystem) {
 		String location = subsystem.getLocation();
-		if (locationToSubsystem.remove(location) == null)
-			throw new IllegalArgumentException("Subsystem location does not exist: " + location);
+		locationToSubsystem.remove(location);
 	}
 }