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/25 22:35:29 UTC

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

Author: jwross
Date: Mon Jun 25 20:35:28 2012
New Revision: 1353732

URL: http://svn.apache.org/viewvc?rev=1353732&view=rev
Log:
ARIES-825: Multiple changes.
(1) Subsystem-Content header now supports arbitrary attributes.
(2) Fixed issue where coordination was being ended on embedded subsystem actions.
(3) Added implementation specific default start-order directive value of "0".
(4) Fixed issue when determining whether or not composite subsystems incorrectly used version ranges.

Modified:
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DeployedContentHeader.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemContentHeader.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemManifest.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/VersionRangeAttribute.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/InstallAction.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/RawSubsystemResource.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/StartResourceComparator.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemManifestValidator.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResource.java

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DeployedContentHeader.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DeployedContentHeader.java?rev=1353732&r1=1353731&r2=1353732&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DeployedContentHeader.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DeployedContentHeader.java Mon Jun 25 20:35:28 2012
@@ -187,26 +187,10 @@ public class DeployedContentHeader imple
 	}
 	
 	private static Collection<Clause> processHeader(String value) {
-		int numOfChars = value.length();
-		StringBuilder builder = new StringBuilder(numOfChars);
-		int numOfQuotes = 0;
-		Set<Clause> clauses = new HashSet<Clause>();
-		for (char c : value.toCharArray()) {
-			numOfChars--;
-			if (c == ',') {
-				if (numOfQuotes % 2 == 0) {
-					clauses.add(new Clause(builder.toString()));
-					builder = new StringBuilder(numOfChars);
-				}
-				else
-					builder.append(c);
-			}
-			else if (c == '"')
-				numOfQuotes++;
-			else
-				builder.append(c);
-		}
-		clauses.add(new Clause(builder.toString()));
+		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;
 	}
 	

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemContentHeader.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemContentHeader.java?rev=1353732&r1=1353731&r2=1353732&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemContentHeader.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemContentHeader.java Mon Jun 25 20:35:28 2012
@@ -16,166 +16,381 @@ 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.OsgiIdentityRequirement;
 import org.apache.aries.subsystem.core.internal.ResourceHelper;
-import org.osgi.framework.Constants;
 import org.osgi.framework.Version;
 import org.osgi.framework.VersionRange;
-import org.osgi.framework.namespace.IdentityNamespace;
-import org.osgi.resource.Capability;
 import org.osgi.resource.Requirement;
 import org.osgi.resource.Resource;
 import org.osgi.service.subsystem.SubsystemConstants;
 
-public class SubsystemContentHeader extends AbstractHeader {
-	public static class Content {
-		private final boolean mandatory;
-		private final String name;
-		private final int startOrder;
-		private final String type;
-		private final VersionRange versionRange;
-		
-		public Content(boolean mandatory, String name, String type, VersionRange versionRange, int startOrder) {
-			this.mandatory = mandatory;
-			this.name = name;
-			this.type = type;
-			this.versionRange = versionRange;
-			this.startOrder = startOrder;
+public class SubsystemContentHeader implements RequirementHeader<SubsystemContentHeader.Clause> {
+	public static class Clause implements org.apache.aries.subsystem.core.archive.Clause {
+		public static final String ATTRIBUTE_VERSION = VersionRangeAttribute.NAME;
+		public static final String ATTRIBUTE_TYPE = TypeAttribute.NAME;
+		public static final String DIRECTIVE_RESOLUTION = ResolutionDirective.NAME;
+		public static final String DIRECTIVE_STARTORDER = StartOrderDirective.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);
+			parameter = parameters.get(ATTRIBUTE_VERSION);
+			if (parameter == null)
+				parameters.put(ATTRIBUTE_VERSION, VersionRangeAttribute.DEFAULT);
+			parameter = parameters.get(DIRECTIVE_RESOLUTION);
+			if (parameter == null)
+				parameters.put(DIRECTIVE_RESOLUTION, ResolutionDirective.MANDATORY);
+			parameter = parameters.get(DIRECTIVE_STARTORDER);
+			if (parameter == null)
+				// This is an implementation specific start-order directive
+				// value. The specification states there is no default value.
+				parameters.put(DIRECTIVE_STARTORDER, new StartOrderDirective("0"));
+		}
+		
+		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());
+				if (parameter instanceof VersionAttribute)
+					parameter = new VersionRangeAttribute(new VersionRange(String.valueOf(parameter.getValue())));
+				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))
+					&& getVersionRange().includes(
+							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;
+		}
+
+		@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 getName() {
-			return name;
+		public String getSymbolicName() {
+			return path;
 		}
 		
 		public int getStartOrder() {
-			return startOrder;
+			return ((StartOrderDirective)getDirective(DIRECTIVE_STARTORDER)).getStartOrder();
 		}
 		
 		public String getType() {
-			return type;
+			return ((TypeAttribute)getAttribute(ATTRIBUTE_TYPE)).getType();
 		}
 		
 		public VersionRange getVersionRange() {
-			return versionRange;
+			return ((VersionRangeAttribute)getAttribute(ATTRIBUTE_VERSION)).getVersionRange();
 		}
 		
 		public boolean isMandatory() {
-			return mandatory;
+			return ((ResolutionDirective)getDirective(DIRECTIVE_RESOLUTION)).isMandatory();
 		}
 		
-		public Requirement toRequirement() {
-			return new OsgiIdentityRequirement(name, versionRange, type, false);
+		public OsgiIdentityRequirement toRequirement(Resource resource) {
+			return new OsgiIdentityRequirement(getSymbolicName(), getVersionRange(), getType(), false);
 		}
 		
+		@Override
 		public String toString() {
-			return new StringBuilder(getName())
-				.append(';')
-				.append(VersionAttribute.NAME)
-				.append('=')
-				.append(getVersionRange())
-				.append(';')
-				.append(TypeAttribute.NAME)
-				.append("=")
-				.append(getType())
-				.append(';')
-				.append(ResolutionDirective.NAME)
-				.append(":=")
-				.append(isMandatory())
-				.append(';')
-				.append(StartOrderDirective.NAME)
-				.append(":=")
-				.append(getStartOrder())
-				.toString();
+			StringBuilder builder = new StringBuilder()
+					.append(getPath());
+			for (Parameter parameter : getParameters()) {
+				builder.append(';').append(parameter);
+			}
+			return builder.toString();
 		}
 	}
 	
+//	public static class Content {
+//		private final boolean mandatory;
+//		private final String name;
+//		private final int startOrder;
+//		private final String type;
+//		private final VersionRange versionRange;
+//		
+//		public Content(boolean mandatory, String name, String type, VersionRange versionRange, int startOrder) {
+//			this.mandatory = mandatory;
+//			this.name = name;
+//			this.type = type;
+//			this.versionRange = versionRange;
+//			this.startOrder = startOrder;
+//		}
+//		
+//		public String getName() {
+//			return name;
+//		}
+//		
+//		public int getStartOrder() {
+//			return startOrder;
+//		}
+//		
+//		public String getType() {
+//			return type;
+//		}
+//		
+//		public VersionRange getVersionRange() {
+//			return versionRange;
+//		}
+//		
+//		public boolean isMandatory() {
+//			return mandatory;
+//		}
+//		
+//		public Requirement toRequirement() {
+//			return new OsgiIdentityRequirement(name, versionRange, type, false);
+//		}
+//		
+//		public String toString() {
+//			return new StringBuilder(getName())
+//				.append(';')
+//				.append(VersionAttribute.NAME)
+//				.append('=')
+//				.append(getVersionRange())
+//				.append(';')
+//				.append(TypeAttribute.NAME)
+//				.append("=")
+//				.append(getType())
+//				.append(';')
+//				.append(ResolutionDirective.NAME)
+//				.append(":=")
+//				.append(isMandatory())
+//				.append(';')
+//				.append(StartOrderDirective.NAME)
+//				.append(":=")
+//				.append(getStartOrder())
+//				.toString();
+//		}
+//	}
+	
 	public static final String NAME = SubsystemConstants.SUBSYSTEM_CONTENT;
 	
-	private static String processResources(Collection<Resource> resources) {
-		if (resources.isEmpty())
-			throw new IllegalArgumentException("At least one resource must be specified");
-		StringBuilder sb = new StringBuilder();
+	public static SubsystemContentHeader newInstance(Collection<Resource> resources) {
+		StringBuilder builder = new StringBuilder();
 		for (Resource resource : resources) {
-			Capability c = resource.getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE).get(0);
-			Map<String, Object> a = c.getAttributes();
-			String s = (String)a.get(IdentityNamespace.IDENTITY_NAMESPACE);
-			Version v = (Version)a.get(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE);
-			String t = (String)a.get(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE);
-			sb.append(s).append(';')
-				.append(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE).append('=').append(v).append(';')
-				.append(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE).append('=').append(t).append(',');
+			appendResource(resource, builder);
+			builder.append(',');
 		}
 		// Remove the trailing comma.
-		sb.deleteCharAt(sb.length() - 1);
-		return sb.toString();
+		// TODO Intentionally letting the exception propagate since there must be at least one resource.
+		builder.deleteCharAt(builder.length() - 1);
+		return new SubsystemContentHeader(builder.toString());
 	}
 	
-	private final List<Content> contents;
+	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_VERSION)
+			.append('=')
+			.append(version.toString())
+			.append(';')
+			.append(Clause.ATTRIBUTE_TYPE)
+			.append('=')
+			.append(type);
+		return builder;
+	}
 	
-	public SubsystemContentHeader(String value) {
-		super(NAME, value);
-		contents = new ArrayList<Content>(clauses.size());
-		for (Clause clause : clauses) {
-			boolean mandatory = true;
-			Directive directive = clause.getDirective(ResolutionDirective.NAME);
-			if (directive != null)
-				mandatory = ((ResolutionDirective)directive).isMandatory();
-			String name = clause.getPath();
-			// TODO Assumes all resources are bundles.
-			String type = TypeAttribute.DEFAULT_VALUE;
-			Attribute attribute = clause.getAttribute(TypeAttribute.NAME);
-			if (attribute != null)
-				type = ((TypeAttribute)attribute).getType();
-			VersionRange versionRange = new VersionRange(Version.emptyVersion.toString());
-			attribute = clause.getAttribute(Constants.VERSION_ATTRIBUTE);
-			if (attribute != null) {
-				versionRange = new VersionRange(String.valueOf(attribute.getValue()));
-			}
-			int startOrder = -1;
-			directive = clause.getDirective(StartOrderDirective.NAME);
-			if (directive != null)
-				startOrder = ((StartOrderDirective)directive).getStartOrder();
-			contents.add(new Content(mandatory, name, type, versionRange, startOrder));
-		}
+	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 static String processResources(Collection<Resource> resources) {
+//		if (resources.isEmpty())
+//			throw new IllegalArgumentException("At least one resource must be specified");
+//		StringBuilder sb = new StringBuilder();
+//		for (Resource resource : resources) {
+//			Capability c = resource.getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE).get(0);
+//			Map<String, Object> a = c.getAttributes();
+//			String s = (String)a.get(IdentityNamespace.IDENTITY_NAMESPACE);
+//			Version v = (Version)a.get(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE);
+//			String t = (String)a.get(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE);
+//			sb.append(s).append(';')
+//				.append(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE).append('=').append(v).append(';')
+//				.append(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE).append('=').append(t).append(',');
+//		}
+//		// Remove the trailing comma.
+//		sb.deleteCharAt(sb.length() - 1);
+//		return sb.toString();
+//	}
+	
+	private final Set<Clause> clauses;
+	
+	public SubsystemContentHeader(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 SubsystemContentHeader(Collection<Resource> resources) {
-		this(processResources(resources));
+	public SubsystemContentHeader(String value) {
+		this(processHeader(value));
 	}
 	
+//	public SubsystemContentHeader(Collection<Resource> resources) {
+//		this(processResources(resources));
+//	}
+	
 	public boolean contains(Resource resource) {
-		return getContent(resource) != null;
+		return getClause(resource) != null;
 	}
 	
-	public Content getContent(Resource resource) {
+	public Clause getClause(Resource resource) {
 		String symbolicName = ResourceHelper.getSymbolicNameAttribute(resource);
 		Version version = ResourceHelper.getVersionAttribute(resource);
 		String type = ResourceHelper.getTypeAttribute(resource);
-		for (Content content : contents) {
-			if (symbolicName.equals(content.getName())
-					&& content.getVersionRange().includes(version)
-					&& type.equals(content.getType()))
-				return content;
+		for (Clause clause : clauses) {
+			if (symbolicName.equals(clause.getPath())
+					&& clause.getVersionRange().includes(version)
+					&& type.equals(clause.getType()))
+				return clause;
 		}
 		return null;
 	}
-
-	public Collection<Content> getContents() {
-		return Collections.unmodifiableCollection(contents);
+	
+	@Override
+	public Collection<SubsystemContentHeader.Clause> getClauses() {
+		return Collections.unmodifiableSet(clauses);
 	}
 	
+//	public Content getContent(Resource resource) {
+//		String symbolicName = ResourceHelper.getSymbolicNameAttribute(resource);
+//		Version version = ResourceHelper.getVersionAttribute(resource);
+//		String type = ResourceHelper.getTypeAttribute(resource);
+//		for (Content content : contents) {
+//			if (symbolicName.equals(content.getName())
+//					&& content.getVersionRange().includes(version)
+//					&& type.equals(content.getType()))
+//				return content;
+//		}
+//		return null;
+//	}
+//
+//	public Collection<Content> getContents() {
+//		return Collections.unmodifiableCollection(contents);
+//	}
+	
 	public boolean isMandatory(Resource resource) {
-		Content content = getContent(resource);
-		return content == null ? false : content.isMandatory();
+		Clause clause = getClause(resource);
+		if (clause == null)
+			return false;
+		return clause.isMandatory();
+//		Content content = getContent(resource);
+//		return content == null ? false : content.isMandatory();
+	}
+	
+//	public List<Requirement> toRequirements() {
+//		ArrayList<Requirement> result = new ArrayList<Requirement>(contents.size());
+//		for (Content content : contents)
+//			result.add(content.toRequirement());
+//		return result;
+//	}
+
+	@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;
 	}
 	
-	public List<Requirement> toRequirements() {
-		ArrayList<Requirement> result = new ArrayList<Requirement>(contents.size());
-		for (Content content : contents)
-			result.add(content.toRequirement());
-		return result;
+	@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();
 	}
 }

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemManifest.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemManifest.java?rev=1353732&r1=1353731&r2=1353732&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemManifest.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemManifest.java Mon Jun 25 20:35:28 2012
@@ -38,7 +38,7 @@ public class SubsystemManifest {
 		}
 		
 		public Builder content(Collection<Resource> value) {
-			return value == null || value.isEmpty() ? this : content(new SubsystemContentHeader(value));
+			return value == null || value.isEmpty() ? this : content(SubsystemContentHeader.newInstance(value));
 		}
 		
 		public Builder content(SubsystemContentHeader value) {
@@ -170,7 +170,7 @@ public class SubsystemManifest {
 		}
 		header = headers.get(SUBSYSTEM_CONTENT);
 		if (header == null && content != null && !content.isEmpty()) {
-			headers.put(SubsystemContentHeader.NAME, new SubsystemContentHeader(content));
+			headers.put(SubsystemContentHeader.NAME, SubsystemContentHeader.newInstance(content));
 		}
 		fillInDefaults(headers);
 		this.headers = Collections.unmodifiableMap(headers);

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/VersionRangeAttribute.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/VersionRangeAttribute.java?rev=1353732&r1=1353731&r2=1353732&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/VersionRangeAttribute.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/VersionRangeAttribute.java Mon Jun 25 20:35:28 2012
@@ -18,6 +18,8 @@ import org.osgi.framework.Version;
 import org.osgi.framework.VersionRange;
 
 public class VersionRangeAttribute extends AbstractAttribute {
+	public static final String NAME = Constants.VERSION_ATTRIBUTE;
+	
 	public static final VersionRangeAttribute DEFAULT = new VersionRangeAttribute();
 	
 	private final VersionRange range;

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=1353732&r1=1353731&r2=1353732&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 Mon Jun 25 20:35:28 2012
@@ -73,16 +73,18 @@ public class InstallAction implements Pr
 			coordination.fail(t);
 		}
 		finally {
-			try {
-				coordination.end();
-			}
-			catch (CoordinationException e) {
-				Throwable t = e.getCause();
-				if (t instanceof SubsystemException)
-					throw (SubsystemException)t;
-				if (t instanceof SecurityException)
-					throw (SecurityException)t;
-				throw new SubsystemException(t);
+			if (!embedded) {
+				try {
+					coordination.end();
+				}
+				catch (CoordinationException e) {
+					Throwable t = e.getCause();
+					if (t instanceof SubsystemException)
+						throw (SubsystemException)t;
+					if (t instanceof SecurityException)
+						throw (SecurityException)t;
+					throw new SubsystemException(t);
+				}
 			}
 		}
 		return result;

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=1353732&r1=1353731&r2=1353732&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 Mon Jun 25 20:35:28 2012
@@ -269,7 +269,7 @@ public class RawSubsystemResource implem
 		LocalRepository localRepo = new LocalRepository(resources);
 		RepositoryServiceRepository serviceRepo = new RepositoryServiceRepository(Activator.getInstance().getBundleContext());
 		CompositeRepository compositeRepo = new CompositeRepository(localRepo, serviceRepo);
-		List<Requirement> requirements = header.toRequirements();
+		List<Requirement> requirements = header.toRequirements(this);
 		List<Resource> resources = new ArrayList<Resource>(requirements.size());
 		for (Requirement requirement : requirements) {
 			Collection<Capability> capabilities = compositeRepo.findProviders(requirement);
@@ -299,7 +299,7 @@ public class RawSubsystemResource implem
 	private SubsystemContentHeader computeSubsystemContentHeader(SubsystemManifest manifest) {
 		SubsystemContentHeader header = manifest.getSubsystemContentHeader();
 		if (header == null && !resources.isEmpty())
-			header = new SubsystemContentHeader(resources);
+			header = SubsystemContentHeader.newInstance(resources);
 		return header;
 	}
 	

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=1353732&r1=1353731&r2=1353732&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 Mon Jun 25 20:35:28 2012
@@ -30,18 +30,28 @@ public abstract class ResourceInstaller 
 		this.resource = resource;
 		this.subsystem = subsystem;
 		if (transitive) {
+			// The resource is a dependency and not content.
 			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)
 			return;
 		Activator.getInstance().getSubsystems().addConstituent(provisionTo, resource);
@@ -59,6 +69,7 @@ public abstract class ResourceInstaller 
 	}
 	
 	protected void addReference(final Resource resource) {
+		// subsystem will be null when a persisted subsystem is being installed
 		if (subsystem == null)
 			return;
 		Activator.getInstance().getSubsystems().addReference(subsystem, resource);

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/StartResourceComparator.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/StartResourceComparator.java?rev=1353732&r1=1353731&r2=1353732&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/StartResourceComparator.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/StartResourceComparator.java Mon Jun 25 20:35:28 2012
@@ -19,9 +19,9 @@ public class StartResourceComparator imp
 	}
 	
 	private Integer getStartOrder(Resource r) {
-		SubsystemContentHeader.Content content = header.getContent(r);
-		if (content == null)
+		SubsystemContentHeader.Clause clause = header.getClause(r);
+		if (clause == null)
 			return 0;
-		return content.getStartOrder();
+		return clause.getStartOrder();
 	}
 }

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemManifestValidator.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemManifestValidator.java?rev=1353732&r1=1353731&r2=1353732&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemManifestValidator.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemManifestValidator.java Mon Jun 25 20:35:28 2012
@@ -3,7 +3,6 @@ package org.apache.aries.subsystem.core.
 import org.apache.aries.subsystem.core.archive.PreferredProviderHeader;
 import org.apache.aries.subsystem.core.archive.SubsystemContentHeader;
 import org.apache.aries.subsystem.core.archive.SubsystemManifest;
-import org.osgi.framework.VersionRange;
 import org.osgi.service.subsystem.SubsystemConstants;
 import org.osgi.service.subsystem.SubsystemException;
 
@@ -14,10 +13,9 @@ public class SubsystemManifestValidator 
 			SubsystemContentHeader header = manifest.getSubsystemContentHeader();
 			if (header == null)
 				return;
-			for (SubsystemContentHeader.Content content : header.getContents()) {
-				// TODO Need to update this to use the new VersionRange.isExact() method, which is more robust.
-				if (!isExactVersion(content.getVersionRange()))
-					throw new SubsystemException("Composite subsystem using version range for content: " + content);
+			for (SubsystemContentHeader.Clause clause : header.getClauses()) {
+				if (clause.getVersionRange().isExact())
+					throw new SubsystemException("Composite subsystem using version range for content: " + clause);
 			}
 		}
 		else if (subsystem.isFeature()) {
@@ -28,16 +26,6 @@ public class SubsystemManifestValidator 
 		}
 	}
 	
-	// TODO Replace this with the new isExact() method on OSGi VersionRange.
-	private static boolean isExactVersion(VersionRange range) {
-		if (range.getLeftType() == VersionRange.LEFT_CLOSED
-		          && range.getLeft().equals(range.getRight())
-		          && range.getRightType() == VersionRange.RIGHT_CLOSED) {
-		     return true;
-		}
-		return false;
-	}
-	
 	private static void validatePreferredProviderHeader(PreferredProviderHeader header) {
 		if (header == null)
 			return;

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=1353732&r1=1353731&r2=1353732&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 Mon Jun 25 20:35:28 2012
@@ -294,13 +294,13 @@ public class SubsystemResource implement
 		SubsystemContentHeader contentHeader = manifest.getSubsystemContentHeader();
 		if (contentHeader == null)
 			return;
-		for (SubsystemContentHeader.Content content : contentHeader.getContents()) {
+		for (SubsystemContentHeader.Clause clause : contentHeader.getClauses()) {
 			OsgiIdentityRequirement requirement = new OsgiIdentityRequirement(
-					content.getName(), content.getVersionRange(),
-					content.getType(), false);
+					clause.getSymbolicName(), clause.getVersionRange(),
+					clause.getType(), false);
 			Resource resource = findContent(requirement);
 			if (resource == null) {
-				if (content.isMandatory())
+				if (clause.isMandatory())
 					throw new SubsystemException("Resource does not exist: "+ requirement);
 				continue;
 			}