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/28 23:22:09 UTC

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

Author: jwross
Date: Tue Feb 28 22:22:08 2012
New Revision: 1294857

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

Initial support for Provide-Capability header in composites.

Added:
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ProvideCapabilityCapability.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ProvideCapabilityHeader.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemExportServiceHeader.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/TypedAttribute.java
Modified:
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/AbstractAttribute.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/AbstractDirective.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/AbstractParameter.java
    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/Directive.java
    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/ExportPackageCapability.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/Parameter.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/TypeAttribute.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/VersionAttribute.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/AriesSubsystem.java

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/AbstractAttribute.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/AbstractAttribute.java?rev=1294857&r1=1294856&r2=1294857&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/AbstractAttribute.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/AbstractAttribute.java Tue Feb 28 22:22:08 2012
@@ -14,7 +14,7 @@
 package org.apache.aries.subsystem.core.archive;
 
 public abstract class AbstractAttribute extends AbstractParameter implements Attribute {
-	public AbstractAttribute(String name, String value) {
+	public AbstractAttribute(String name, Object value) {
 		super(name, value);
 	}
 	

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/AbstractDirective.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/AbstractDirective.java?rev=1294857&r1=1294856&r2=1294857&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/AbstractDirective.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/AbstractDirective.java Tue Feb 28 22:22:08 2012
@@ -17,6 +17,10 @@ public abstract class AbstractDirective 
 	public AbstractDirective(String name, String value) {
 		super(name, value);
 	}
+	
+	public String getValue() {
+		return (String)super.getValue();
+	}
 
 	public String toString() {
 		return new StringBuilder()

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/AbstractParameter.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/AbstractParameter.java?rev=1294857&r1=1294856&r2=1294857&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/AbstractParameter.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/AbstractParameter.java Tue Feb 28 22:22:08 2012
@@ -15,9 +15,9 @@ package org.apache.aries.subsystem.core.
 
 public abstract class AbstractParameter implements Parameter {
 	private final String myName;
-	private final String myValue;
+	private final Object myValue;
 	
-	public AbstractParameter(String name, String value) {
+	public AbstractParameter(String name, Object value) {
 		myName = name;
 		myValue = value;
 	}
@@ -26,7 +26,7 @@ public abstract class AbstractParameter 
 		return myName;
 	}
 	
-	public String getValue() {
+	public Object getValue() {
 		return myValue;
 	}
 }

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=1294857&r1=1294856&r2=1294857&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 Tue Feb 28 22:22:08 2012
@@ -32,9 +32,10 @@ import org.osgi.service.subsystem.Subsys
 
 public class DeploymentManifest {
 	public static final String DEPLOYED_CONTENT = SubsystemConstants.DEPLOYED_CONTENT;
-	public static final String DEPLOYMENT_MANIFESTVERSION = "Deployment-ManifestVersion"; // TODO Needs constant on SubsystemConstants.
+	public static final String DEPLOYMENT_MANIFESTVERSION = SubsystemConstants.DEPLOYMENT_MANIFESTVERSION;
 	public static final String EXPORT_PACKAGE = Constants.EXPORT_PACKAGE;
 	public static final String IMPORT_PACKAGE = Constants.IMPORT_PACKAGE;
+	public static final String PROVIDE_CAPABILITY = Constants.PROVIDE_CAPABILITY;
 	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;
@@ -133,6 +134,9 @@ public class DeploymentManifest {
 				header = subsystemManifest.getExportPackageHeader();
 				if (header != null)
 					headers.put(EXPORT_PACKAGE, header);
+				header = subsystemManifest.getProvideCapabilityHeader();
+				if (header != null)
+					headers.put(PROVIDE_CAPABILITY, header);
 				// TODO Compute additional headers for a composite. 
 			}
 			// Features require no additional headers.
@@ -164,6 +168,10 @@ public class DeploymentManifest {
 		return (ImportPackageHeader)getHeaders().get(IMPORT_PACKAGE);
 	}
 	
+	public ProvideCapabilityHeader getProvideCapabilityHeader() {
+		return (ProvideCapabilityHeader)getHeaders().get(PROVIDE_CAPABILITY);
+	}
+	
 	public ProvisionResourceHeader getProvisionResourceHeader() {
 		return (ProvisionResourceHeader)getHeaders().get(PROVISION_RESOURCE);
 	}

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Directive.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Directive.java?rev=1294857&r1=1294856&r2=1294857&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Directive.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Directive.java Tue Feb 28 22:22:08 2012
@@ -14,4 +14,5 @@
 package org.apache.aries.subsystem.core.archive;
 
 public interface Directive extends Parameter {
+	String getValue();
 }

Modified: 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=1294857&r1=1294856&r2=1294857&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/EffectiveDirective.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/EffectiveDirective.java Tue Feb 28 22:22:08 2012
@@ -10,6 +10,8 @@ public class EffectiveDirective extends 
 	public static final EffectiveDirective ACTIVE = new EffectiveDirective(VALUE_ACTIVE);
 	public static final EffectiveDirective RESOLVE = new EffectiveDirective(VALUE_RESOLVE);
 	
+	public static final EffectiveDirective DEFAULT = RESOLVE;
+	
 	public static EffectiveDirective getInstance(String value) {
 		if (VALUE_ACTIVE.equals(value))
 			return ACTIVE;

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ExportPackageCapability.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ExportPackageCapability.java?rev=1294857&r1=1294856&r2=1294857&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ExportPackageCapability.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ExportPackageCapability.java Tue Feb 28 22:22:08 2012
@@ -22,7 +22,7 @@ public class ExportPackageCapability ext
 			if (parameter instanceof Attribute)
 				attributes.put(parameter.getName(), parameter.getValue());
 			else
-				directives.put(parameter.getName(), parameter.getValue());
+				directives.put(parameter.getName(), ((Directive)parameter).getValue());
 		}
 		this.resource = resource;
 	}

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=1294857&r1=1294856&r2=1294857&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 Tue Feb 28 22:22:08 2012
@@ -125,6 +125,13 @@ public interface Grammar {
 	public static final String EXPORT = PACKAGENAMES + "(?:;\\s*(?:" + PARAMETER + "))*";
 	public static final String EXPORT_PACKAGE = EXPORT + "(?:,\\s*(?:" + EXPORT + "))*";
 	
+	public static final String SCALAR = "String|Version|Long|Double";
+	public static final String LIST = "List<(?:" + SCALAR + ")>";
+	public static final String TYPE = "(?:" + SCALAR + ")|" + LIST;
+	public static final String TYPED_ATTR = EXTENDED + "(?:\\:" + TYPE + ")?=(?:" + ARGUMENT + ')';
+	public static final String CAPABILITY = NAMESPACE + "(?:;\\s*(?:(?:" + DIRECTIVE + ")|(?:" + TYPED_ATTR + ")))*";
+	public static final String PROVIDE_CAPABILITY = CAPABILITY + "(?:,\\s*(?:" + CAPABILITY + "))*";
+	
 	/*
 	 * 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=1294857&r1=1294856&r2=1294857&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 Tue Feb 28 22:22:08 2012
@@ -101,6 +101,8 @@ public class HeaderFactory {
 			return new SubsystemImportServiceHeader(value);
 		if (RequireBundleHeader.NAME.equals(name))
 			return new RequireBundleHeader(value);
+		if (ProvideCapabilityHeader.NAME.equals(name))
+			return new ProvideCapabilityHeader(value);
 		return new GenericHeader(name, value);
 			
 	}

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Parameter.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Parameter.java?rev=1294857&r1=1294856&r2=1294857&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Parameter.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Parameter.java Tue Feb 28 22:22:08 2012
@@ -16,5 +16,5 @@ package org.apache.aries.subsystem.core.
 public interface Parameter {
 	String getName();
 	
-	String getValue();
+	Object getValue();
 }

Added: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ProvideCapabilityCapability.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ProvideCapabilityCapability.java?rev=1294857&view=auto
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ProvideCapabilityCapability.java (added)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ProvideCapabilityCapability.java Tue Feb 28 22:22:08 2012
@@ -0,0 +1,46 @@
+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.AbstractCapability;
+import org.osgi.resource.Resource;
+
+public class ProvideCapabilityCapability extends AbstractCapability {
+	private final Map<String, Object> attributes = new HashMap<String, Object>();
+	private final Map<String, String> directives = new HashMap<String, String>();
+	private final String namespace;
+	private final Resource resource;
+	
+	public ProvideCapabilityCapability(ProvideCapabilityHeader.Clause clause, Resource resource) {
+		namespace = clause.getNamespace();
+		for (Parameter parameter : clause.getParameters()) {
+			if (parameter instanceof Attribute)
+				attributes.put(parameter.getName(), parameter.getValue());
+			else
+				directives.put(parameter.getName(), ((Directive)parameter).getValue());
+		}
+		this.resource = resource;
+	}
+
+	@Override
+	public Map<String, Object> getAttributes() {
+		return Collections.unmodifiableMap(attributes);
+	}
+
+	@Override
+	public Map<String, String> getDirectives() {
+		return Collections.unmodifiableMap(directives);
+	}
+
+	@Override
+	public String getNamespace() {
+		return namespace;
+	}
+
+	@Override
+	public Resource getResource() {
+		return resource;
+	}
+}

Added: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ProvideCapabilityHeader.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ProvideCapabilityHeader.java?rev=1294857&view=auto
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ProvideCapabilityHeader.java (added)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/ProvideCapabilityHeader.java Tue Feb 28 22:22:08 2012
@@ -0,0 +1,179 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+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 ProvideCapabilityHeader implements Header<ProvideCapabilityHeader.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_USES = Constants.USES_DIRECTIVE;
+		
+		private static final String DIRECTIVE = '(' + Grammar.EXTENDED + ")(:=)(" + Grammar.ARGUMENT + ')';
+		private static final String TYPED_ATTR = '(' + Grammar.EXTENDED + ")(?:(\\:)(" + Grammar.TYPE + "))?=(" + Grammar.ARGUMENT + ')';
+		private static final Pattern PATTERN_NAMESPACE = Pattern.compile('(' + Grammar.NAMESPACE + ")(?=;|\\z)");
+		private static final Pattern PATTERN_PARAMETER = Pattern.compile("(?:(?:" + DIRECTIVE + ")|(?:" + TYPED_ATTR + "))(?=;|\\z)");
+		
+		private static void fillInDefaults(Map<String, Parameter> parameters) {
+			Parameter parameter = parameters.get(DIRECTIVE_EFFECTIVE);
+			if (parameter == null)
+				parameters.put(DIRECTIVE_EFFECTIVE, EffectiveDirective.DEFAULT);
+		}
+		
+		private final String path;
+		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);
+			path = matcher.group();
+			matcher.usePattern(PATTERN_PARAMETER);
+			while (matcher.find()) {
+				if (":=".equals(matcher.group(2))) {
+					// This is a directive.
+					parameters.put(matcher.group(1), DirectiveFactory.createDirective(matcher.group(1), matcher.group(3)));
+				}
+				else if (":".equals(matcher.group(5)))
+					// This is a typed attribute with a declared version.
+					parameters.put(matcher.group(4), new TypedAttribute(matcher.group(4), matcher.group(7), matcher.group(6)));
+				else
+					// This is a typed attribute without a declared version.
+					parameters.put(matcher.group(4), new TypedAttribute(matcher.group(4), matcher.group(7), TypedAttribute.Type.String));
+			}
+			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((TypedAttribute)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 path;
+		}
+
+		@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;
+		}
+		
+		@Override
+		public String toString() {
+			StringBuilder builder = new StringBuilder()
+					.append(getPath());
+			for (Parameter parameter : getParameters()) {
+				builder.append(';').append(parameter);
+			}
+			return builder.toString();
+		}
+	}
+	
+	public static final String NAME = Constants.PROVIDE_CAPABILITY;
+	
+	private static final Pattern PATTERN = Pattern.compile('(' + Grammar.CAPABILITY + ")(?=,|\\z)");
+	
+	private final Set<Clause> clauses = new HashSet<Clause>();
+	
+	public ProvideCapabilityHeader(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<ProvideCapabilityHeader.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();
+	}
+}

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=1294857&r1=1294856&r2=1294857&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 Tue Feb 28 22:22:08 2012
@@ -105,7 +105,7 @@ public class SubsystemContentHeader exte
 			VersionRange versionRange = new VersionRange(Version.emptyVersion.toString());
 			attribute = clause.getAttribute(Constants.VERSION_ATTRIBUTE);
 			if (attribute != null) {
-				versionRange = new VersionRange(attribute.getValue());
+				versionRange = new VersionRange(String.valueOf(attribute.getValue()));
 			}
 			int startOrder = StartOrderDirective.DEFAULT_VALUE;
 			directive = clause.getDirective(StartOrderDirective.NAME);

Added: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemExportServiceHeader.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemExportServiceHeader.java?rev=1294857&view=auto
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemExportServiceHeader.java (added)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemExportServiceHeader.java Tue Feb 28 22:22:08 2012
@@ -0,0 +1,194 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+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;
+import org.osgi.resource.Resource;
+import org.osgi.service.subsystem.SubsystemConstants;
+
+public class SubsystemExportServiceHeader implements Header<SubsystemExportServiceHeader.Clause> {
+	public static class Clause implements org.apache.aries.subsystem.core.archive.Clause {
+		public static final String ATTRIBUTE_VERSION = Constants.VERSION_ATTRIBUTE;
+		public static final String DIRECTIVE_EXCLUDE = Constants.EXCLUDE_DIRECTIVE;
+		public static final String DIRECTIVE_INCLUDE = Constants.INCLUDE_DIRECTIVE;
+		public static final String DIRECTIVE_MANDATORY = Constants.MANDATORY_DIRECTIVE;
+		public static final String DIRECTIVE_USES = Constants.USES_DIRECTIVE;
+		
+		private static final Pattern PATTERN_PACKAGENAME = Pattern.compile('(' + Grammar.PACKAGENAME + ")(?=;|\\z)");
+		private static final Pattern PATTERN_PACKAGENAMES = Pattern.compile('(' + Grammar.PACKAGENAMES + ")(?=;|\\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_VERSION);
+			if (parameter == null)
+				parameters.put(ATTRIBUTE_VERSION, VersionAttribute.DEFAULT);
+		}
+		
+		private final Collection<String> packageNames = new HashSet<String>();
+		private final String path;
+		private final Map<String, Parameter> parameters = new HashMap<String, Parameter>();
+		
+		public Clause(String clause) {
+			Matcher main = PATTERN_PACKAGENAMES.matcher(clause);
+			if (!main.find())
+				throw new IllegalArgumentException("Missing package names path: " + clause);
+			path = main.group();
+			Matcher path = PATTERN_PACKAGENAME.matcher(this.path);
+			while (path.find())
+				packageNames.add(main.group());
+			main.usePattern(PATTERN_PARAMETER);
+			while (main.find()) {
+				Parameter parameter = ParameterFactory.create(main.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 Collection<String> getPackageNames() {
+			return Collections.unmodifiableCollection(packageNames);
+		}
+
+		@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 Collection<ExportPackageCapability> toCapabilities(Resource resource) {
+			Collection<ExportPackageCapability> result = new ArrayList<ExportPackageCapability>(packageNames.size());
+			for (String packageName : packageNames)
+				result.add(new ExportPackageCapability(packageName, parameters.values(), resource));
+			return result;
+		}
+		
+		@Override
+		public String toString() {
+			StringBuilder builder = new StringBuilder()
+					.append(getPath());
+			for (Parameter parameter : getParameters()) {
+				builder.append(';').append(parameter);
+			}
+			return builder.toString();
+		}
+	}
+	
+	public static final String NAME = SubsystemConstants.SUBSYSTEM_EXPORTSERVICE;
+	
+	// TODO Subsystem-ExportService currently does not have its own grammar, but it's similar to Provide-Capability.
+	private static final Pattern PATTERN = Pattern.compile('(' + Grammar.CAPABILITY + ")(?=,|\\z)");
+	
+	private final Set<Clause> clauses = new HashSet<Clause>();
+	
+	public SubsystemExportServiceHeader(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<SubsystemExportServiceHeader.Clause> getClauses() {
+		return Collections.unmodifiableSet(clauses);
+	}
+
+	@Override
+	public String getName() {
+		return NAME;
+	}
+
+	@Override
+	public String getValue() {
+		return toString();
+	}
+	
+	public Collection<ExportPackageCapability> toCapabilities(Resource resource) {
+		Collection<ExportPackageCapability> result = new ArrayList<ExportPackageCapability>();
+		for (Clause clause : clauses)
+			result.addAll(clause.toCapabilities(resource));
+		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=1294857&r1=1294856&r2=1294857&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 Tue Feb 28 22:22:08 2012
@@ -118,6 +118,10 @@ public class SubsystemManifest {
 		return (ImportPackageHeader)getHeaders().get(IMPORT_PACKAGE);
 	}
 	
+	public ProvideCapabilityHeader getProvideCapabilityHeader() {
+		return (ProvideCapabilityHeader)getHeaders().get(PROVIDE_CAPABILITY);
+	}
+	
 	public RequireBundleHeader getRequireBundleHeader() {
 		return (RequireBundleHeader)getHeaders().get(REQUIRE_BUNDLE);
 	}

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/TypeAttribute.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/TypeAttribute.java?rev=1294857&r1=1294856&r2=1294857&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/TypeAttribute.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/TypeAttribute.java Tue Feb 28 22:22:08 2012
@@ -35,6 +35,6 @@ public class TypeAttribute extends Abstr
 	}
 
 	public String getType() {
-		return getValue();
+		return (String)getValue();
 	}
 }

Added: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/TypedAttribute.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/TypedAttribute.java?rev=1294857&view=auto
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/TypedAttribute.java (added)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/TypedAttribute.java Tue Feb 28 22:22:08 2012
@@ -0,0 +1,40 @@
+package org.apache.aries.subsystem.core.archive;
+
+import org.osgi.framework.Version;
+
+public class TypedAttribute extends AbstractAttribute {
+	public static enum Type {
+		Double,
+		Long,
+		String,
+		Version
+	}
+	
+	private static Object parseValue(String value, Type type) {
+		switch (type) {
+			case Double:
+				return Double.valueOf(value);
+			case Long:
+				return Long.valueOf(value);
+			case Version:
+				return Version.parseVersion(value);
+			default:
+				return value;
+		}
+	}
+	
+	private final Type type;
+	
+	public TypedAttribute(String name, String value, String type) {
+		this(name, value, Type.valueOf(type));
+	}
+	
+	public TypedAttribute(String name, String value, Type type) {
+		super(name, parseValue(value, type));
+		this.type = type;
+	}
+	
+	public Type getType() {
+		return type;
+	}
+}

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/VersionAttribute.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/VersionAttribute.java?rev=1294857&r1=1294856&r2=1294857&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/VersionAttribute.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/VersionAttribute.java Tue Feb 28 22:22:08 2012
@@ -29,7 +29,7 @@ public class VersionAttribute extends Ab
 	
 	public VersionAttribute(String value) {
 		super(NAME, value);
-		version = Version.parseVersion(getValue());
+		version = Version.parseVersion(value);
 	}
 
 	public Version getVersion() {

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=1294857&r1=1294856&r2=1294857&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 Feb 28 22:22:08 2012
@@ -51,6 +51,8 @@ import org.apache.aries.subsystem.core.a
 import org.apache.aries.subsystem.core.archive.Header;
 import org.apache.aries.subsystem.core.archive.ImportPackageHeader;
 import org.apache.aries.subsystem.core.archive.ImportPackageRequirement;
+import org.apache.aries.subsystem.core.archive.ProvideCapabilityCapability;
+import org.apache.aries.subsystem.core.archive.ProvideCapabilityHeader;
 import org.apache.aries.subsystem.core.archive.ProvisionResourceHeader;
 import org.apache.aries.subsystem.core.archive.ProvisionResourceHeader.ProvisionedResource;
 import org.apache.aries.subsystem.core.archive.RequireBundleHeader;
@@ -1049,6 +1051,7 @@ public class AriesSubsystem implements S
 		RegionFilterBuilder builder = from.getRegionDigraph().createRegionFilterBuilder();
 		if (isComposite()) {
 			setExportIsolationPolicy(builder, getDeploymentManifest().getExportPackageHeader());
+			setExportIsolationPolicy(builder, getDeploymentManifest().getProvideCapabilityHeader());
 			// TODO Implement export isolation policy for composites.
 		}
 		RegionFilter regionFilter = builder.build();
@@ -1072,6 +1075,22 @@ public class AriesSubsystem implements S
 			builder.allow(policy, filter.toString());
 		}
 	}
+	
+	private void setExportIsolationPolicy(RegionFilterBuilder builder, ProvideCapabilityHeader header) throws InvalidSyntaxException {
+		if (header == null)
+			return;
+		for (ProvideCapabilityHeader.Clause clause : header.getClauses()) {
+			ProvideCapabilityCapability capability = new ProvideCapabilityCapability(clause, this);
+			String policy = capability.getNamespace();
+			StringBuilder filter = new StringBuilder("(&");
+			for (Entry<String, Object> attribute : capability.getAttributes().entrySet())
+				filter.append('(').append(attribute.getKey()).append('=').append(attribute.getValue()).append(')');
+			filter.append(')');
+			if (LOGGER.isDebugEnabled())
+				LOGGER.debug("Allowing " + policy + " of " + filter);
+			builder.allow(policy, filter.toString());
+		}
+	}
 
 	private void setImportIsolationPolicy() throws BundleException, IOException, InvalidSyntaxException {
 		if (isRoot())