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/02/26 17:28:58 UTC

svn commit: r1293864 - 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/subsystem/ite...

Author: jwross
Date: Sun Feb 26 16:28:57 2012
New Revision: 1293864

URL: http://svn.apache.org/viewvc?rev=1293864&view=rev
Log:
ARIES-825: Update subsystems to latest Subsystem, Resolver, and Repository APIs.

(1) Added initial support for composite require-capability header.
(2) Added new composite test.

Added:
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/EffectiveDirective.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/RequireCapabilityHeader.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/RequireCapabilityRequirement.java
Modified:
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DeploymentManifest.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DirectiveFactory.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Grammar.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/HeaderFactory.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ImportPackageRequirement.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ResolutionDirective.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemManifest.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/AriesSubsystem.java
    aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/CompositeTest.java

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DeploymentManifest.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DeploymentManifest.java?rev=1293864&r1=1293863&r2=1293864&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DeploymentManifest.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DeploymentManifest.java Sun Feb 26 16:28:57 2012
@@ -39,6 +39,7 @@ public class DeploymentManifest {
 	public static final String IMPORT_PACKAGE = Constants.IMPORT_PACKAGE;
 	public static final String PROVISION_RESOURCE = SubsystemConstants.PROVISION_RESOURCE;
 	public static final String REQUIRE_BUNDLE = Constants.REQUIRE_BUNDLE;
+	public static final String REQUIRE_CAPABILITY = Constants.REQUIRE_CAPABILITY;
 	public static final String SUBSYSTEM_SYMBOLICNAME = SubsystemConstants.SUBSYSTEM_SYMBOLICNAME;
 	public static final String SUBSYSTEM_VERSION = SubsystemConstants.SUBSYSTEM_VERSION;
 	
@@ -111,16 +112,19 @@ public class DeploymentManifest {
 			SubsystemTypeHeader typeHeader = subsystemManifest.getSubsystemTypeHeader();
 			if (SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION.equals(typeHeader.getValue())) {
 				if (resolution != null) {
-					ImportPackageHeader header = computeImportPackageHeader(resolution, deployedContent, acceptDependencies);
+					Header<?> header = computeImportPackageHeader(resolution, deployedContent, acceptDependencies);
 					if (header != null)
 						headers.put(IMPORT_PACKAGE, header);
 				}
 				// TODO Compute additional headers for an application.
 			}
 			else if (SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE.equals(typeHeader.getValue())) {
-				ImportPackageHeader importPackage = subsystemManifest.getImportPackageHeader();
-				if (importPackage != null)
-					headers.put(IMPORT_PACKAGE, importPackage);
+				Header<?> header = subsystemManifest.getImportPackageHeader();
+				if (header != null)
+					headers.put(IMPORT_PACKAGE, header);
+				header = subsystemManifest.getRequireCapabilityHeader();
+				if (header != null)
+					headers.put(REQUIRE_CAPABILITY, header);
 				// TODO Compute additional headers for a composite. 
 			}
 			// Features require no additional headers.
@@ -152,6 +156,10 @@ public class DeploymentManifest {
 		return (ProvisionResourceHeader)getHeaders().get(PROVISION_RESOURCE);
 	}
 	
+	public RequireCapabilityHeader getRequireCapabilityHeader() {
+		return (RequireCapabilityHeader)getHeaders().get(REQUIRE_CAPABILITY);
+	}
+	
 	public void write(OutputStream out) throws IOException {
 		Manifest manifest = new Manifest();
 		Attributes attributes = manifest.getMainAttributes();

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DirectiveFactory.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DirectiveFactory.java?rev=1293864&r1=1293863&r2=1293864&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DirectiveFactory.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DirectiveFactory.java Sun Feb 26 16:28:57 2012
@@ -21,6 +21,8 @@ public class DirectiveFactory {
 			return new StartOrderDirective(value);
 		if (FilterDirective.NAME.equals(name))
 			return new FilterDirective(value);
+		if (EffectiveDirective.NAME.equals(name))
+			return EffectiveDirective.getInstance(value);
 		return new GenericDirective(name, value);
 	}
 }

Added: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/EffectiveDirective.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/EffectiveDirective.java?rev=1293864&view=auto
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/EffectiveDirective.java (added)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/EffectiveDirective.java Sun Feb 26 16:28:57 2012
@@ -0,0 +1,36 @@
+package org.apache.aries.subsystem.core.archive;
+
+import org.osgi.framework.Constants;
+
+public class EffectiveDirective extends AbstractDirective {
+	public static final String NAME = Constants.EFFECTIVE_DIRECTIVE;
+	public static final String VALUE_ACTIVE = Constants.EFFECTIVE_ACTIVE;
+	public static final String VALUE_RESOLVE = Constants.EFFECTIVE_RESOLVE;
+	
+	public static final EffectiveDirective ACTIVE = new EffectiveDirective(VALUE_ACTIVE);
+	public static final EffectiveDirective RESOLVE = new EffectiveDirective(VALUE_RESOLVE);
+	
+	public static EffectiveDirective getInstance(String value) {
+		if (VALUE_ACTIVE.equals(value))
+			return ACTIVE;
+		if (VALUE_RESOLVE.equals(value))
+			return RESOLVE;
+		return new EffectiveDirective(value);
+	}
+	
+	public EffectiveDirective() {
+		this(Constants.EFFECTIVE_RESOLVE);
+	}
+	
+	public EffectiveDirective(String value) {
+		super(NAME, value);
+	}
+	
+	public boolean isActive() {
+		return ACTIVE == this || Constants.EFFECTIVE_ACTIVE.equals(getValue());
+	}
+	
+	public boolean isResolve() {
+		return RESOLVE == this || Constants.EFFECTIVE_RESOLVE.equals(getValue());
+	}
+}

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Grammar.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Grammar.java?rev=1293864&r1=1293863&r2=1293864&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Grammar.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Grammar.java Sun Feb 26 16:28:57 2012
@@ -115,6 +115,10 @@ public interface Grammar {
 	public static final String IMPORT = PACKAGENAMES + "(?:;\\s*(?:" + PARAMETER + "))*";
 	public static final String IMPORTPACKAGE = IMPORT + "(?:\\,\\s*" + IMPORT + ")*";
 	
+	public static final String NAMESPACE = SYMBOLICNAME;
+	public static final String REQUIREMENT = NAMESPACE + "(?:;\\s*(?:" + PARAMETER + "))*";
+	public static final String REQUIRE_CAPABILITY = REQUIREMENT + "(?:,\\s*(?:" + REQUIREMENT + "))*";
+	
 	/*
 	 * number ::= digit+
 	 * version ::= major( '.' minor ( '.' micro ( '.' qualifier )? )? )?

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/HeaderFactory.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/HeaderFactory.java?rev=1293864&r1=1293863&r2=1293864&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/HeaderFactory.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/HeaderFactory.java Sun Feb 26 16:28:57 2012
@@ -96,6 +96,8 @@ public class HeaderFactory {
 			return new ProvisionResourceHeader(value);
 		if (SubsystemManifestVersionHeader.NAME.equals(name))
 			return new SubsystemManifestVersionHeader(value);
+		if (RequireCapabilityHeader.NAME.equals(name))
+			return new RequireCapabilityHeader(value);
 		return new GenericHeader(name, value);
 			
 	}

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ImportPackageRequirement.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ImportPackageRequirement.java?rev=1293864&r1=1293863&r2=1293864&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ImportPackageRequirement.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ImportPackageRequirement.java Sun Feb 26 16:28:57 2012
@@ -10,23 +10,17 @@ import org.osgi.framework.namespace.Pack
 import org.osgi.resource.Resource;
 
 public class ImportPackageRequirement extends AbstractRequirement {
-	private static final String BUNDLE_SYMBOLICNAME = PackageNamespace.CAPABILITY_BUNDLE_SYMBOLICNAME_ATTRIBUTE;
-	private static final String BUNDLE_VERSION = PackageNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE;
-	private static final String EQUAL = "=";
-	private static final String FILTER = PackageNamespace.REQUIREMENT_FILTER_DIRECTIVE;
-	private static final String GREATER_THAN = ">";
-	private static final String GREATER_THAN_OR_EQUAL = GREATER_THAN + EQUAL;
-	private static final String LESS_THAN = "<";
-	private static final String LESS_THAN_OR_EQUAL = LESS_THAN + EQUAL;
-	private static final String NAMESPACE = PackageNamespace.PACKAGE_NAMESPACE;
-	private static final String RESOLUTION = PackageNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE;
-	private static final String RESOLUTION_MANDATORY = PackageNamespace.RESOLUTION_MANDATORY;
-	private static final String RESOLUTION_OPTIONAL = PackageNamespace.RESOLUTION_OPTIONAL;
-	private static final String VERSION = PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE;
+	public static final String DIRECTIVE_FILTER = PackageNamespace.REQUIREMENT_FILTER_DIRECTIVE;
+	public static final String NAMESPACE = PackageNamespace.PACKAGE_NAMESPACE;
 	
 	private final Map<String, String> directives = new HashMap<String, String>(1);
+	private final Resource resource;
 	
 	public ImportPackageRequirement(ImportPackageHeader.Clause clause) {
+		this(clause, null);
+	}
+	
+	public ImportPackageRequirement(ImportPackageHeader.Clause clause, Resource resource) {
 		Collection<String> packageNames = clause.getPackageNames();
 		if (packageNames.isEmpty() || packageNames.size() > 1)
 			throw new IllegalArgumentException("Only one package name per requirement allowed");
@@ -36,7 +30,8 @@ public class ImportPackageRequirement ex
 		if (versionRange != null) {
 			versionRange.appendToFilter(filter);
 		}
-		directives.put(FILTER, filter.append(')').toString());
+		directives.put(DIRECTIVE_FILTER, filter.append(')').toString());
+		this.resource = resource;
 	}
 	
 	@Override
@@ -51,11 +46,11 @@ public class ImportPackageRequirement ex
 
 	@Override
 	public String getNamespace() {
-		return PackageNamespace.PACKAGE_NAMESPACE;
+		return NAMESPACE;
 	}
 
 	@Override
 	public Resource getResource() {
-		return null;
+		return resource;
 	}
 }

Added: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/RequireCapabilityHeader.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/RequireCapabilityHeader.java?rev=1293864&view=auto
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/RequireCapabilityHeader.java (added)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/RequireCapabilityHeader.java Sun Feb 26 16:28:57 2012
@@ -0,0 +1,150 @@
+package org.apache.aries.subsystem.core.archive;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.osgi.framework.Constants;
+
+public class RequireCapabilityHeader implements Header<RequireCapabilityHeader.Clause> {
+	public static class Clause implements org.apache.aries.subsystem.core.archive.Clause {
+		public static final String DIRECTIVE_EFFECTIVE = Constants.EFFECTIVE_DIRECTIVE;
+		public static final String DIRECTIVE_FILTER = Constants.FILTER_DIRECTIVE;
+		public static final String DIRECTIVE_RESOLUTION = Constants.RESOLUTION_DIRECTIVE;
+		
+		private static final Pattern PATTERN_NAMESPACE = Pattern.compile('(' + Grammar.NAMESPACE + ")(?=;|\\z)");
+		private static final Pattern PATTERN_PARAMETER = Pattern.compile('(' + Grammar.PARAMETER + ")(?=;|\\z)");
+		
+		private static void fillInDefaults(Map<String, Parameter> parameters) {
+			Parameter parameter = parameters.get(DIRECTIVE_EFFECTIVE);
+			if (parameter == null)
+				parameters.put(DIRECTIVE_EFFECTIVE, EffectiveDirective.RESOLVE);
+			parameter = parameters.get(DIRECTIVE_RESOLUTION);
+			if (parameter == null)
+				parameters.put(DIRECTIVE_RESOLUTION, ResolutionDirective.MANDATORY);
+		}
+		
+		private final String namespace;
+		private final Map<String, Parameter> parameters = new HashMap<String, Parameter>();
+		
+		public Clause(String clause) {
+			Matcher matcher = PATTERN_NAMESPACE.matcher(clause);
+			if (!matcher.find())
+				throw new IllegalArgumentException("Missing namespace path: " + clause);
+			namespace = matcher.group();
+			matcher.usePattern(PATTERN_PARAMETER);
+			while (matcher.find()) {
+				Parameter parameter = ParameterFactory.create(matcher.group());
+				parameters.put(parameter.getName(), parameter);
+			}
+			fillInDefaults(parameters);
+		}
+		
+		@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;
+		}
+		
+		public String getNamespace() {
+			return namespace;
+		}
+
+		@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 getNamespace();
+		}
+	}
+	
+	public static final String NAME = Constants.REQUIRE_CAPABILITY;
+	
+	private static final Pattern PATTERN = Pattern.compile('(' + Grammar.REQUIREMENT + ")(?=,|\\z)");
+	
+	private final Set<Clause> clauses = new HashSet<Clause>();
+	
+	public RequireCapabilityHeader(String value) {
+		Matcher matcher = PATTERN.matcher(value);
+		while (matcher.find())
+			clauses.add(new Clause(matcher.group()));
+		if (clauses.isEmpty())
+			throw new IllegalArgumentException("A " + NAME + " header must have at least one clause");
+	}
+
+	@Override
+	public Collection<RequireCapabilityHeader.Clause> getClauses() {
+		return Collections.unmodifiableSet(clauses);
+	}
+
+	@Override
+	public String getName() {
+		return NAME;
+	}
+
+	@Override
+	public String getValue() {
+		return toString();
+	}
+	
+	@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/RequireCapabilityRequirement.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/RequireCapabilityRequirement.java?rev=1293864&view=auto
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/RequireCapabilityRequirement.java (added)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/RequireCapabilityRequirement.java Sun Feb 26 16:28:57 2012
@@ -0,0 +1,49 @@
+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.resource.AbstractRequirement;
+import org.osgi.resource.Namespace;
+import org.osgi.resource.Resource;
+
+public class RequireCapabilityRequirement extends AbstractRequirement {
+	public static final String DIRECTIVE_FILTER = Namespace.REQUIREMENT_FILTER_DIRECTIVE;
+	
+	private final Map<String, String> directives = new HashMap<String, String>(1);
+	private final String namespace;
+	private final Resource resource;
+	
+	public RequireCapabilityRequirement(RequireCapabilityHeader.Clause clause) {
+		this(clause, null);
+	}
+	
+	public RequireCapabilityRequirement(RequireCapabilityHeader.Clause clause, Resource resource) {
+		namespace = clause.getNamespace();
+		Directive filter = clause.getDirective(RequireCapabilityHeader.Clause.DIRECTIVE_FILTER);
+		if (filter != null)
+			directives.put(DIRECTIVE_FILTER, filter.getValue());
+		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/archive/ResolutionDirective.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ResolutionDirective.java?rev=1293864&r1=1293863&r2=1293864&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ResolutionDirective.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ResolutionDirective.java Sun Feb 26 16:28:57 2012
@@ -17,35 +17,34 @@ import org.osgi.framework.Constants;
 
 public class ResolutionDirective extends AbstractDirective {
 	public static final String NAME = Constants.RESOLUTION_DIRECTIVE;
+	public static final String VALUE_MANDATORY = Constants.RESOLUTION_MANDATORY;
+	public static final String VALUE_OPTIONAL = Constants.RESOLUTION_OPTIONAL;
 	
-	public static final ResolutionDirective MANDATORY = new ResolutionDirective(true);
-	public static final ResolutionDirective OPTIONAL = new ResolutionDirective(false);
+	public static final ResolutionDirective MANDATORY = new ResolutionDirective(VALUE_MANDATORY);
+	public static final ResolutionDirective OPTIONAL = new ResolutionDirective(VALUE_OPTIONAL);
+	
+	public ResolutionDirective() {
+		this(VALUE_MANDATORY);
+	}
 	
 	public static ResolutionDirective getInstance(String value) {
-		if (Constants.RESOLUTION_MANDATORY.equals(value)) {
+		if (VALUE_MANDATORY.equals(value))
 			return MANDATORY;
-		}
-		else if (Constants.RESOLUTION_OPTIONAL.equals(value)) {
+		if (VALUE_OPTIONAL.equals(value))
 			return OPTIONAL;
-		}
-		else {
-			throw new IllegalArgumentException("Illegal " + Constants.RESOLUTION_DIRECTIVE + " value: " + value);
-		}
-		
+		else
+			throw new IllegalArgumentException("Invalid " + Constants.RESOLUTION_DIRECTIVE + " directive: " + value);
 	}
 	
-	private final boolean mandatory;
-	
-	private ResolutionDirective(boolean mandatory) {
-		super(NAME, mandatory ? Constants.RESOLUTION_MANDATORY : Constants.RESOLUTION_OPTIONAL);
-		this.mandatory = mandatory;
+	private ResolutionDirective(String value) {
+		super(NAME, value);
 	}
 
 	public boolean isMandatory() {
-		return mandatory;
+		return MANDATORY == this || VALUE_MANDATORY.equals(getValue());
 	}
 	
 	public boolean isOptional() {
-		return !mandatory;
+		return OPTIONAL == this || VALUE_OPTIONAL.equals(getValue());
 	}
 }

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=1293864&r1=1293863&r2=1293864&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 Sun Feb 26 16:28:57 2012
@@ -114,6 +114,10 @@ public class SubsystemManifest {
 		return (ImportPackageHeader)getHeaders().get(IMPORT_PACKAGE);
 	}
 	
+	public RequireCapabilityHeader getRequireCapabilityHeader() {
+		return (RequireCapabilityHeader)getHeaders().get(REQUIRE_CAPABILITY);
+	}
+	
 	public SubsystemContentHeader getSubsystemContentHeader() {
 		return (SubsystemContentHeader)getHeaders().get(SUBSYSTEM_CONTENT);
 	}

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=1293864&r1=1293863&r2=1293864&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/AriesSubsystem.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/AriesSubsystem.java Sun Feb 26 16:28:57 2012
@@ -51,6 +51,8 @@ import org.apache.aries.subsystem.core.a
 import org.apache.aries.subsystem.core.archive.ImportPackageRequirement;
 import org.apache.aries.subsystem.core.archive.ProvisionResourceHeader;
 import org.apache.aries.subsystem.core.archive.ProvisionResourceHeader.ProvisionedResource;
+import org.apache.aries.subsystem.core.archive.RequireCapabilityHeader;
+import org.apache.aries.subsystem.core.archive.RequireCapabilityRequirement;
 import org.apache.aries.subsystem.core.archive.SubsystemArchive;
 import org.apache.aries.subsystem.core.archive.SubsystemManifest;
 import org.apache.aries.subsystem.core.obr.SubsystemEnvironment;
@@ -69,7 +71,6 @@ import org.osgi.framework.BundleExceptio
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.Version;
 import org.osgi.framework.namespace.IdentityNamespace;
-import org.osgi.framework.namespace.PackageNamespace;
 import org.osgi.framework.wiring.BundleRevision;
 import org.osgi.framework.wiring.FrameworkWiring;
 import org.osgi.resource.Capability;
@@ -1045,28 +1046,22 @@ public class AriesSubsystem implements S
 			// Features share the same isolation as that of their scoped parent.
 			return;
 		if (isApplication() || isComposite()) {
+			Region from = region;
+			Region to = ((AriesSubsystem)getParents().iterator().next()).region;
+			RegionFilterBuilder builder = from.getRegionDigraph().createRegionFilterBuilder();
 			// Both applications and composites have Import-Package headers that require processing.
 			// In the case of applications, the header is generated.
-			ImportPackageHeader importPackage = getDeploymentManifest().getImportPackageHeader();
-			if (importPackage != null) {
-				Region from = region;
-				Region to = ((AriesSubsystem)getParents().iterator().next()).region;
-				String policy = RegionFilter.VISIBLE_PACKAGE_NAMESPACE;
-				RegionFilterBuilder builder = from.getRegionDigraph().createRegionFilterBuilder();
-				for (ImportPackageHeader.Clause clause : importPackage.getClauses()) {
-					ImportPackageRequirement requirement = new ImportPackageRequirement(clause);
-					String filter = requirement.getDirectives().get(PackageNamespace.REQUIREMENT_FILTER_DIRECTIVE);
-					if (LOGGER.isDebugEnabled())
-						LOGGER.debug("Allowing " + policy + " of " + filter);
-					builder.allow(policy, filter);
-				}
-				RegionFilter regionFilter = builder.build();
-				if (LOGGER.isDebugEnabled())
-					LOGGER.debug("Establishing region connection: from="
-							+ from + ", to=" + to + ", policy=" + policy
-							+ ", filter=" + regionFilter);
-				from.connectRegion(to, regionFilter);
-			}
+			Header<?> header = getDeploymentManifest().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 = getDeploymentManifest().getRequireCapabilityHeader();
+			setImportIsolationPolicy(builder, (RequireCapabilityHeader)header);
+			RegionFilter regionFilter = builder.build();
+			if (LOGGER.isDebugEnabled())
+				LOGGER.debug("Establishing region connection: from=" + from
+						+ ", to=" + to + ", filter=" + regionFilter);
+			from.connectRegion(to, regionFilter);
 		}
 		if (isApplication()) {
 			// TODO Implement import isolation policy for applications.
@@ -1077,6 +1072,32 @@ public class AriesSubsystem implements S
 			// Composites specify an explicit import policy in their subsystem and deployment manifests.
 		}
 	}
+	
+	private static 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);
+			String filter = requirement.getDirectives().get(ImportPackageRequirement.DIRECTIVE_FILTER);
+			if (LOGGER.isDebugEnabled())
+				LOGGER.debug("Allowing " + policy + " of " + filter);
+			builder.allow(policy, filter);
+		}
+	}
+	
+	private static void setImportIsolationPolicy(RegionFilterBuilder builder, RequireCapabilityHeader header) throws InvalidSyntaxException {
+		if (header == null)
+			return;
+		for (RequireCapabilityHeader.Clause clause : header.getClauses()) {
+			RequireCapabilityRequirement requirement = new RequireCapabilityRequirement(clause);
+			String policy = requirement.getNamespace();
+			String filter = requirement.getDirectives().get(RequireCapabilityRequirement.DIRECTIVE_FILTER);
+			if (LOGGER.isDebugEnabled())
+				LOGGER.debug("Allowing " + policy + " of " + filter);
+			builder.allow(policy, filter);
+		}
+	}
 
 	private void startBundleResource(Resource resource, Coordination coordination) throws BundleException {
 		final Bundle bundle = ((BundleRevision)resource).getBundle();

Modified: aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/CompositeTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/CompositeTest.java?rev=1293864&r1=1293863&r2=1293864&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/CompositeTest.java (original)
+++ aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/CompositeTest.java Sun Feb 26 16:28:57 2012
@@ -22,8 +22,11 @@ public class CompositeTest extends Subsy
 		if (createdTestFiles)
 			return;
 		createBundleA();
-		createCompositeC();
+		createBundleB();
 		createBundleC();
+		createBundleE();
+		createCompositeC();
+		createCompositeD();
 		createdTestFiles = true;
 	}
 	
@@ -39,6 +42,19 @@ public class CompositeTest extends Subsy
 						.end());
 	}
 	
+	private static void createBundleB() throws IOException {
+		write("bundle.b.jar",
+				ArchiveFixture
+						.newJar()
+						.manifest()
+						.symbolicName(
+								"org.apache.aries.subsystem.itests.bundle.b")
+						.version("1.0.0")
+						.attribute(Constants.PROVIDE_CAPABILITY,
+								"y; y=test; version:Version=1.0")
+						.end());
+	}
+	
 	private static void createBundleC() throws IOException {
 		write("bundle.c.jar",
 				ArchiveFixture
@@ -51,6 +67,19 @@ public class CompositeTest extends Subsy
 						.end());
 	}
 	
+	private static void createBundleE() throws IOException {
+		write("bundle.e.jar",
+				ArchiveFixture
+						.newJar()
+						.manifest()
+						.symbolicName(
+								"org.apache.aries.subsystem.itests.bundle.e")
+						.version("1.0.0")
+						.attribute(Constants.REQUIRE_CAPABILITY,
+								"y; filter:=(y=test)")
+						.end());
+	}
+	
 	private static void createCompositeC() throws IOException {
 		createCompositeCManifest();
 		write("composite.c.esa",
@@ -58,6 +87,13 @@ public class CompositeTest extends Subsy
 						new FileInputStream("COMPOSITE.C.MF")));
 	}
 	
+	private static void createCompositeD() throws IOException {
+		createCompositeDManifest();
+		write("composite.d.esa",
+				ArchiveFixture.newZip().binary("OSGI-INF/SUBSYSTEM.MF",
+						new FileInputStream("COMPOSITE.D.MF")));
+	}
+	
 	private static void createCompositeCManifest() throws IOException {
 		write("COMPOSITE.C.MF",
 				ArchiveFixture
@@ -71,6 +107,19 @@ public class CompositeTest extends Subsy
 								"org.apache.aries.subsystem.itests.bundle.a.x, does.not.exist; a=b"));
 	}
 	
+	private static void createCompositeDManifest() throws IOException {
+		write("COMPOSITE.D.MF",
+				ArchiveFixture
+						.newJar()
+						.manifest()
+						.attribute(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME,
+								"org.apache.aries.subsystem.itests.subsystem.composite.d")
+						.attribute(SubsystemConstants.SUBSYSTEM_TYPE,
+								SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE)
+						.attribute(Constants.REQUIRE_CAPABILITY,
+								"y; filter:=\"(y=test)\", does.not.exist; filter:=\"(a=b)\""));
+	}
+	
 	@Test
 	public void testImportPackage() throws Exception {
 		Bundle bundleA = installBundleFromFile("bundle.a.jar");
@@ -93,4 +142,27 @@ public class CompositeTest extends Subsy
 			bundleA.uninstall();
 		}
 	}
+	
+	@Test
+	public void testRequireCapability() throws Exception {
+		Bundle bundleB = installBundleFromFile("bundle.b.jar");
+		try {
+			Subsystem compositeD = installSubsystemFromFile("composite.d.esa");
+			try {
+				Bundle bundleE = installBundleFromFile("bundle.e.jar", compositeD);
+				try {
+					startBundle(bundleE, compositeD);
+				}
+				finally {
+					bundleE.uninstall();
+				}
+			}
+			finally {
+				uninstallScopedSubsystem(compositeD);
+			}
+		}
+		finally {
+			bundleB.uninstall();
+		}
+	}
 }