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/07/03 17:24:51 UTC

svn commit: r1356787 - in /aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core: archive/ internal/

Author: jwross
Date: Tue Jul  3 15:24:50 2012
New Revision: 1356787

URL: http://svn.apache.org/viewvc?rev=1356787&view=rev
Log:
ARIES-825: Multiple changes.
(1) Fixed issue in PreferredProviderHeader where the version attribute was not being treated as a version range.
(2) Added support to the ProvisionResourceHeader for persistence.
(3) Fixed issue when exposing content resource capabilities on a feature that caused an infinite installation loop when a feature had a dependency on a parent feature.
(4) Fixed some issues with accurately representing constituent, parent/child, and resource reference relationships.
(5) Fixed issue where persisted root subsystem did not accurately reflect constituents at restart.

Added:
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ProvisionResourceRequirement.java
Modified:
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/PreferredProviderHeader.java
    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/internal/AriesSubsystem.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/SubsystemResource.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/Subsystems.java

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/PreferredProviderHeader.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/PreferredProviderHeader.java?rev=1356787&r1=1356786&r2=1356787&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/PreferredProviderHeader.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/PreferredProviderHeader.java Tue Jul  3 15:24:50 2012
@@ -44,6 +44,8 @@ public class PreferredProviderHeader imp
 			matcher.usePattern(PATTERN_PARAMETER);
 			while (matcher.find()) {
 				Parameter parameter = ParameterFactory.create(matcher.group());
+				if (parameter instanceof VersionAttribute)
+					parameter = new VersionRangeAttribute(new VersionRange(String.valueOf(parameter.getValue())));
 				parameters.put(parameter.getName(), parameter);
 			}
 			fillInDefaults(parameters);

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=1356787&r1=1356786&r2=1356787&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 Tue Jul  3 15:24:50 2012
@@ -16,45 +16,145 @@ package org.apache.aries.subsystem.core.
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import org.apache.aries.subsystem.core.internal.ResourceHelper;
+import org.apache.aries.subsystem.core.internal.Utils;
 import org.osgi.framework.Version;
+import org.osgi.resource.Requirement;
 import org.osgi.resource.Resource;
+import org.osgi.service.subsystem.SubsystemConstants;
 
-public class ProvisionResourceHeader extends AbstractHeader {
-	public static class ProvisionedResource {
-		private final Version deployedVersion;
-		private final String name;
-		private final String namespace;
-		private final long resourceId;
-		
-		public ProvisionedResource(String name, Version deployedVersion, String namespace, long resourceId) {
-			this.name = name;
-			this.deployedVersion = deployedVersion;
-			this.namespace = namespace;
-			this.resourceId = resourceId;
+public class ProvisionResourceHeader implements RequirementHeader<ProvisionResourceHeader.Clause> {
+	public static class Clause implements org.apache.aries.subsystem.core.archive.Clause {
+		public static final String ATTRIBUTE_DEPLOYEDVERSION = DeployedVersionAttribute.NAME;
+		public static final String ATTRIBUTE_RESOURCEID = "resourceId";
+		public static final String ATTRIBUTE_TYPE = TypeAttribute.NAME;
+		
+		private static final Pattern PATTERN_SYMBOLICNAME = Pattern.compile('(' + Grammar.SYMBOLICNAME + ")(?=;|\\z)");
+		private static final Pattern PATTERN_PARAMETER = Pattern.compile('(' + Grammar.PARAMETER + ")(?=;|\\z)");
+		
+		private static void fillInDefaults(Map<String, Parameter> parameters) {
+			Parameter parameter = parameters.get(ATTRIBUTE_TYPE);
+			if (parameter == null)
+				parameters.put(ATTRIBUTE_TYPE, TypeAttribute.DEFAULT);
+		}
+		
+		private final String path;
+		private final Map<String, Parameter> parameters = new HashMap<String, Parameter>();
+		
+		public Clause(String clause) {
+			Matcher matcher = PATTERN_SYMBOLICNAME.matcher(clause);
+			if (!matcher.find())
+				throw new IllegalArgumentException("Missing symbolic name path: " + clause);
+			path = matcher.group();
+			matcher.usePattern(PATTERN_PARAMETER);
+			while (matcher.find()) {
+				Parameter parameter = ParameterFactory.create(matcher.group());
+				parameters.put(parameter.getName(), parameter);
+			}
+			fillInDefaults(parameters);
+		}
+		
+		public Clause(Resource resource) {
+			this(appendResource(resource, new StringBuilder()).toString());
+		}
+		
+		public boolean contains(Resource resource) {
+			return getSymbolicName().equals(
+					ResourceHelper.getSymbolicNameAttribute(resource))
+					&& getDeployedVersion().equals(
+							ResourceHelper.getVersionAttribute(resource))
+					&& getType().equals(
+							ResourceHelper.getTypeAttribute(resource));
+		}
+		
+		@Override
+		public Attribute getAttribute(String name) {
+			Parameter result = parameters.get(name);
+			if (result instanceof Attribute)
+				return (Attribute)result;
+			return null;
+		}
+
+		@Override
+		public Collection<Attribute> getAttributes() {
+			ArrayList<Attribute> attributes = new ArrayList<Attribute>(parameters.size());
+			for (Parameter parameter : parameters.values())
+				if (parameter instanceof Attribute)
+					attributes.add((Attribute)parameter);
+			attributes.trimToSize();
+			return attributes;
 		}
 		
 		public Version getDeployedVersion() {
-			return deployedVersion;
+			return ((DeployedVersionAttribute)getAttribute(ATTRIBUTE_DEPLOYEDVERSION)).getVersion();
+		}
+
+		@Override
+		public Directive getDirective(String name) {
+			Parameter result = parameters.get(name);
+			if (result instanceof Directive)
+				return (Directive)result;
+			return null;
+		}
+
+		@Override
+		public Collection<Directive> getDirectives() {
+			ArrayList<Directive> directives = new ArrayList<Directive>(parameters.size());
+			for (Parameter parameter : parameters.values())
+				if (parameter instanceof Directive)
+					directives.add((Directive)parameter);
+			directives.trimToSize();
+			return directives;
+		}
+
+		@Override
+		public Parameter getParameter(String name) {
+			return parameters.get(name);
+		}
+
+		@Override
+		public Collection<Parameter> getParameters() {
+			return Collections.unmodifiableCollection(parameters.values());
+		}
+
+		@Override
+		public String getPath() {
+			return path;
+		}
+		
+		public String getSymbolicName() {
+			return path;
 		}
+
 		
-		public String getName() {
-			return name;
+		public String getType() {
+			return ((TypeAttribute)getAttribute(ATTRIBUTE_TYPE)).getType();
 		}
 		
-		public String getNamespace() {
-			return namespace;
+		public ProvisionResourceRequirement toRequirement(Resource resource) {
+			return new ProvisionResourceRequirement(this, resource);
 		}
 		
-		public long getResourceId() {
-			return resourceId;
+		@Override
+		public String toString() {
+			StringBuilder builder = new StringBuilder()
+					.append(getPath());
+			for (Parameter parameter : getParameters()) {
+				builder.append(';').append(parameter);
+			}
+			return builder.toString();
 		}
 	}
 	
-	// TODO Needs to be added to SubsystemConstants.
-	public static final String NAME = "Provision-Resource";
+	public static final String NAME = SubsystemConstants.PROVISION_RESOURCE;
 	
 	public static ProvisionResourceHeader newInstance(Collection<Resource> resources) {
 		StringBuilder builder = new StringBuilder();
@@ -68,42 +168,97 @@ public class ProvisionResourceHeader ext
 		return new ProvisionResourceHeader(builder.toString());
 	}
 	
-	private final List<ProvisionedResource> provisionedResources;
+	private static StringBuilder appendResource(Resource resource, StringBuilder builder) {
+		String symbolicName = ResourceHelper.getSymbolicNameAttribute(resource);
+		Version version = ResourceHelper.getVersionAttribute(resource);
+		String type = ResourceHelper.getTypeAttribute(resource);
+		builder.append(symbolicName)
+			.append(';')
+			.append(Clause.ATTRIBUTE_DEPLOYEDVERSION)
+			.append('=')
+			.append(version.toString())
+			.append(';')
+			.append(Clause.ATTRIBUTE_TYPE)
+			.append('=')
+			.append(type)
+			.append(';')
+			.append(Clause.ATTRIBUTE_RESOURCEID)
+			.append('=')
+			.append(Utils.getId(resource));
+		return builder;
+	}
+	
+	private static Collection<Clause> processHeader(String value) {
+		Collection<String> clauseStrs = new ClauseTokenizer(value).getClauses();
+		Set<Clause> clauses = new HashSet<Clause>(clauseStrs.size());
+		for (String clause : new ClauseTokenizer(value).getClauses())
+			clauses.add(new Clause(clause));
+		return clauses;
+	}
+	
+	private final Set<Clause> clauses;
+	
+	public ProvisionResourceHeader(Collection<Clause> clauses) {
+		if (clauses.isEmpty())
+			throw new IllegalArgumentException("A " + NAME + " header must have at least one clause");
+		this.clauses = new HashSet<Clause>(clauses);
+	}
 	
 	public ProvisionResourceHeader(String value) {
-		super(NAME, value);
-		provisionedResources = new ArrayList<ProvisionedResource>(clauses.size());
-		for (Clause clause : clauses) {
-			DeployedVersionAttribute attribute = (DeployedVersionAttribute)clause.getAttribute(DeployedVersionAttribute.NAME);
-			TypeAttribute typeAttribute = (TypeAttribute)clause.getAttribute(TypeAttribute.NAME);
-			Attribute resourceId = clause.getAttribute(DeployedContentHeader.Clause.ATTRIBUTE_RESOURCEID);
-			provisionedResources.add(
-					new ProvisionedResource(
-							clause.getPath(),
-							attribute == null ? Version.emptyVersion : attribute.getDeployedVersion(),
-							typeAttribute == null ? TypeAttribute.DEFAULT_VALUE : typeAttribute.getType(),
-							resourceId == null ? -1 : Long.parseLong(String.valueOf(resourceId.getValue()))));
-		}
+		this(processHeader(value));
 	}
 	
 	public boolean contains(Resource resource) {
-		return getProvisionedResource(resource) != null;
+		for (Clause clause : getClauses())
+			if (clause.contains(resource))
+				return true;
+		return false;
 	}
 	
-	public ProvisionedResource getProvisionedResource(Resource resource) {
+	public Clause getClause(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;
+		for (Clause clause : clauses) {
+			if (symbolicName.equals(clause.getPath())
+					&& clause.getDeployedVersion().equals(version)
+					&& type.equals(clause.getType()))
+				return clause;
 		}
 		return null;
 	}
 
-	public List<ProvisionedResource> getProvisionedResources() {
-		return Collections.unmodifiableList(provisionedResources);
+	@Override
+	public Collection<ProvisionResourceHeader.Clause> getClauses() {
+		return Collections.unmodifiableSet(clauses);
+	}
+
+	@Override
+	public String getName() {
+		return NAME;
+	}
+
+	@Override
+	public String getValue() {
+		return toString();
+	}
+	
+	@Override
+	public List<Requirement> toRequirements(Resource resource) {
+		List<Requirement> requirements = new ArrayList<Requirement>(clauses.size());
+		for (Clause clause : clauses)
+			requirements.add(clause.toRequirement(resource));
+		return requirements;
+	}
+	
+	@Override
+	public String toString() {
+		StringBuilder builder = new StringBuilder();
+		for (Clause clause : getClauses()) {
+			builder.append(clause).append(',');
+		}
+		// Remove the trailing comma. Note at least one clause is guaranteed to exist.
+		builder.deleteCharAt(builder.length() - 1);
+		return builder.toString();
 	}
 }

Added: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ProvisionResourceRequirement.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ProvisionResourceRequirement.java?rev=1356787&view=auto
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ProvisionResourceRequirement.java (added)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ProvisionResourceRequirement.java Tue Jul  3 15:24:50 2012
@@ -0,0 +1,48 @@
+package org.apache.aries.subsystem.core.archive;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.aries.subsystem.core.internal.AbstractRequirement;
+import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.resource.Resource;
+
+public class ProvisionResourceRequirement extends AbstractRequirement {
+	public static final String DIRECTIVE_FILTER = IdentityNamespace.REQUIREMENT_FILTER_DIRECTIVE;
+	public static final String NAMESPACE = IdentityNamespace.IDENTITY_NAMESPACE;
+	
+	private final Map<String, String> directives = new HashMap<String, String>();
+	private final Resource resource;
+	
+	public ProvisionResourceRequirement(
+			ProvisionResourceHeader.Clause clause, Resource resource) {
+		StringBuilder builder = new StringBuilder("(&(")
+				.append(NAMESPACE).append('=')
+				.append(clause.getSymbolicName()).append(')');
+		for (Attribute attribute : clause.getAttributes())
+			attribute.appendToFilter(builder);
+		directives.put(DIRECTIVE_FILTER, builder.append(')').toString());
+		this.resource = resource;
+	}
+
+	@Override
+	public Map<String, Object> getAttributes() {
+		return Collections.emptyMap();
+	}
+
+	@Override
+	public Map<String, String> getDirectives() {
+		return Collections.unmodifiableMap(directives);
+	}
+
+	@Override
+	public String getNamespace() {
+		return NAMESPACE;
+	}
+
+	@Override
+	public Resource getResource() {
+		return resource;
+	}
+}

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=1356787&r1=1356786&r2=1356787&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/AriesSubsystem.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/AriesSubsystem.java Tue Jul  3 15:24:50 2012
@@ -28,6 +28,7 @@ import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleException;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.Version;
+import org.osgi.framework.namespace.IdentityNamespace;
 import org.osgi.resource.Capability;
 import org.osgi.resource.Requirement;
 import org.osgi.resource.Resource;
@@ -118,13 +119,13 @@ public class AriesSubsystem implements R
 		// TODO Somehow, exposing the capabilities of content resources of a
 		// feature is causing an infinite regression of feature2 installations
 		// in FeatureTest.testSharedContent() under certain conditions.
-//		if (isScoped() || IdentityNamespace.IDENTITY_NAMESPACE.equals(namespace))
-//			return result;
-//		SubsystemContentHeader header = manifest.getSubsystemContentHeader();
-//		for (Resource constituent : getConstituents())
-//			if (header.contains(constituent))
-//				for (Capability capability : constituent.getCapabilities(namespace))
-//					result.add(new BasicCapability(capability, this));
+		if (isScoped() || IdentityNamespace.IDENTITY_NAMESPACE.equals(namespace))
+			return result;
+		SubsystemContentHeader header = manifest.getSubsystemContentHeader();
+		for (Resource constituent : getConstituents())
+			if (header.contains(constituent))
+				for (Capability capability : constituent.getCapabilities(namespace))
+					result.add(new BasicCapability(capability, this));
 		return result;
 	}
 

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=1356787&r1=1356786&r2=1356787&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 Tue Jul  3 15:24:50 2012
@@ -1,5 +1,6 @@
 package org.apache.aries.subsystem.core.internal;
 
+import org.apache.aries.subsystem.core.archive.DeployedContentHeader;
 import org.apache.aries.subsystem.core.archive.DeploymentManifest;
 import org.apache.aries.subsystem.core.archive.ProvisionResourceHeader;
 import org.osgi.framework.namespace.IdentityNamespace;
@@ -31,32 +32,23 @@ public abstract class ResourceInstaller 
 		this.coordination = coordination;
 		this.resource = resource;
 		this.subsystem = subsystem;
-		if (isTransitive()) {
-			// The resource is a dependency and not content.
+		if (isDependency()) {
 			if (Utils.isInstallableResource(resource))
-				// If the dependency needs to be installed, it must go into the
-				// first subsystem in the parent chain that accepts
-				// dependencies.
 				provisionTo = Utils.findFirstSubsystemAcceptingDependenciesStartingFrom(subsystem);
 			else
-				// If the dependency has already been installed, it does not
-				// need to be provisioned.
 				provisionTo = null;
 		}
 		else
-			// The resource is content and must go into the subsystem declaring
-			// it as such.
 			provisionTo = subsystem;
 	}
 	
 	public abstract Resource install() throws Exception;
 	
 	protected void addConstituent(final Resource resource) {
-		// provisionTo will be null when the resource is an already installed
-		// dependency.
-		if (provisionTo == null)
+		// Don't let a resource become a constituent of itself.
+		if (resource.equals(provisionTo))
 			return;
-		Activator.getInstance().getSubsystems().addConstituent(provisionTo, resource);
+		Activator.getInstance().getSubsystems().addConstituent(provisionTo, resource, isContent());
 		coordination.addParticipant(new Participant() {
 			@Override
 			public void ended(Coordination arg0) throws Exception {
@@ -71,9 +63,8 @@ public abstract class ResourceInstaller 
 	}
 	
 	protected void addReference(final Resource resource) {
-		// subsystem will be null when the root or a persisted subsystem is
-		// being installed
-		if (subsystem == null)
+		// Don't let a resource reference itself.
+		if (resource.equals(subsystem))
 			return;
 		Activator.getInstance().getSubsystems().addReference(subsystem, resource);
 		coordination.addParticipant(new Participant() {
@@ -93,9 +84,15 @@ public abstract class ResourceInstaller 
 		return provisionTo.getSubsystemId() + "@" + provisionTo.getSymbolicName() + "@" + ResourceHelper.getSymbolicNameAttribute(resource);
 	}
 	
-	protected boolean isTransitive() {
-		if (subsystem == null)
-			return false;
+	protected boolean isContent() {
+		DeploymentManifest manifest = subsystem.getDeploymentManifest();
+		DeployedContentHeader header = manifest.getDeployedContentHeader();
+		if (header == null)
+			return !isDependency();
+		return header.contains(resource) || !isDependency();
+	}
+	
+	protected boolean isDependency() {
 		DeploymentManifest manifest = subsystem.getDeploymentManifest();
 		if (manifest == null)
 			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=1356787&r1=1356786&r2=1356787&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 Tue Jul  3 15:24:50 2012
@@ -343,10 +343,10 @@ public class SubsystemResource implement
 			ProvisionResourceHeader header = manifest.getProvisionResourceHeader();
 			if (header == null)
 				return;
-			for (ProvisionResourceHeader.ProvisionedResource provisionedResource : header.getProvisionedResources()) {
-				Resource resource = findDependency(provisionedResource);
+			for (ProvisionResourceHeader.Clause clause : header.getClauses()) {
+				Resource resource = findDependency(clause);
 				if (resource == null)
-					throw new SubsystemException("Resource does not exist: " + provisionedResource);
+					throw new SubsystemException("Resource does not exist: " + clause);
 				addDependency(resource);
 			}
 		}	
@@ -521,18 +521,19 @@ public class SubsystemResource implement
 		return findContent(clause.toRequirement(this));
 	}
 	
-	private Resource findDependency(ProvisionResourceHeader.ProvisionedResource provisionedResource) {
-		long resourceId = provisionedResource.getResourceId();
+	private Resource findDependency(ProvisionResourceHeader.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 = provisionedResource.getNamespace();
+			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(
-				provisionedResource.getName(), provisionedResource.getDeployedVersion(),
-				provisionedResource.getNamespace(), false);
+				clause.getPath(), clause.getDeployedVersion(),
+				clause.getType(), true);
 		List<Capability> capabilities = createResolveContext().findProviders(requirement);
 		if (capabilities.isEmpty())
 			return null;

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=1356787&r1=1356786&r2=1356787&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 Tue Jul  3 15:24:50 2012
@@ -30,9 +30,14 @@ public class SubsystemResourceInstaller 
 	}
 	
 	private void addChild(final AriesSubsystem child) {
-		if (provisionTo == null || subsystem == null)
+		// provisionTo will be null if the resource is an already installed
+		// dependency.
+		if (provisionTo == null)
 			return;
-		Activator.getInstance().getSubsystems().addChild(subsystem, child, true);
+		// Don't let a resource become a child of itself.
+		if (resource.equals(provisionTo))
+			return;
+		Activator.getInstance().getSubsystems().addChild(provisionTo, child, !isDependency());
 		coordination.addParticipant(new Participant() {
 			@Override
 			public void ended(Coordination arg0) throws Exception {
@@ -41,7 +46,7 @@ public class SubsystemResourceInstaller 
 
 			@Override
 			public void failed(Coordination arg0) throws Exception {
-				Activator.getInstance().getSubsystems().removeChild(subsystem, child);
+				Activator.getInstance().getSubsystems().removeChild(provisionTo, child);
 			}
 		});
 	}
@@ -64,7 +69,7 @@ public class SubsystemResourceInstaller 
 	private AriesSubsystem installAriesSubsystem(AriesSubsystem subsystem) throws Exception {
 		addChild(subsystem);
 		addConstituent(subsystem);
-		if (!isTransitive())
+		if (!isDependency())
 			addReference(subsystem);
 		// TODO Is this check really necessary?
 		if (!State.INSTALLING.equals(subsystem.getState()))
@@ -73,24 +78,29 @@ public class SubsystemResourceInstaller 
 		if (subsystem.isScoped())
 			RegionContextBundleHelper.installRegionContextBundle(subsystem);
 		Activator.getInstance().getSubsystemServiceRegistrar().register(subsystem, this.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).install();
-			for (Resource dependency : subsystem.getResource().getSharedDependencies())
+		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).install();
+		for (Resource dependency : subsystem.getResource().getSharedDependencies()) {
+			// TODO This needs some more thought. The following check
+			// protects against a child subsystem that has its parent as a
+			// dependency. Are there other places of concern as well? Is it
+			// only the current parent that is of concern or should all
+			// parents be checked?
+			if (!dependency.equals(this.subsystem))
 				ResourceInstaller.newInstance(coordination, dependency, subsystem).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).install();
-			// Simulate installation of shared content so that necessary relationships are established.
-			for (Resource content : subsystem.getResource().getSharedContent())
-				ResourceInstaller.newInstance(coordination, content, subsystem).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).install();
+		// Simulate installation of shared content so that necessary relationships are established.
+		for (Resource content : subsystem.getResource().getSharedContent())
+			ResourceInstaller.newInstance(coordination, content, subsystem).install();
 		subsystem.setState(State.INSTALLED);
 		return subsystem;
 	}

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=1356787&r1=1356786&r2=1356787&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 Tue Jul  3 15:24:50 2012
@@ -34,7 +34,7 @@ public class Subsystems {
 		child.addedParent(parent, referenceCount);
 	}
 	
-	public void addConstituent(AriesSubsystem subsystem, Resource constituent) {
+	public void addConstituent(AriesSubsystem subsystem, Resource constituent, boolean isContent) {
 		synchronized (subsystemToConstituents) {
 			Set<Resource> constituents = subsystemToConstituents.get(subsystem);
 			if (constituents == null) {
@@ -43,7 +43,8 @@ public class Subsystems {
 			}
 			constituents.add(constituent);
 		}
-		subsystem.addedContent(constituent);
+		if (isContent)
+			subsystem.addedContent(constituent);
 	}
 	
 	public void addReference(AriesSubsystem subsystem, Resource resource) {
@@ -112,7 +113,7 @@ public class Subsystems {
 					// graph. At the very least, throw IllegalStateException where
 					// appropriate.
 					graph = new SubsystemGraph(root);
-					ResourceInstaller.newInstance(coordination, root, null).install();
+					ResourceInstaller.newInstance(coordination, root, root).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
@@ -141,7 +142,7 @@ public class Subsystems {
 					}
 					root = getSubsystemById(0);
 					graph = new SubsystemGraph(root);
-					ResourceInstaller.newInstance(coordination, root, null).install();
+					ResourceInstaller.newInstance(coordination, root, root).install();
 					for (AriesSubsystem s : subsystems) {
 						AriesSubsystemParentsHeader header = s.getDeploymentManifest().getAriesSubsystemParentsHeader();
 						if (header == null)