aries-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jwr...@apache.org
Subject svn commit: r1707428 - 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-core/src/test/java/org/apache/aries/subsystem/core/...
Date Thu, 08 Oct 2015 02:13:58 GMT
Author: jwross
Date: Thu Oct  8 02:13:58 2015
New Revision: 1707428

URL: http://svn.apache.org/viewvc?rev=1707428&view=rev
Log:
ARIES-1425 Support both osgi.bundle and osgi.fragment resource types when given a Subsystem-Content
header clause with an unspecified type attribute.

Add one unit test specifically for the Subsystem-Content header behavior.

Add one integration test for bundle versus fragment selection as well as the generated Deployed-Content
header.

Compute default parameters only once.

Check to see if the type attribute was specified and set a flag accordingly. Then add the
default value in order to maintain the equals/hashCode integrity. That is, "foo" equals
"foo;type=osgi.bundle". Maintain a copy of the original value so that the generated subsystem
manifest and header as retrieved from getSubsystemHeaders will reflect whether or
not the type was originally specified. If the type was unspecified, ensure the generated osgi.identity
requirement will match both bundles and fragments.

Discovering content works the same as before in that first the local repository is searched
followed by repository services. Bundles are preferred over fragments within the same
repository. If anything is found in the local repository, the search stops as before and does
not proceed to the repository services. This means that a fragment in the local
repository will be preferred over a bundle in a repository service.

A few unreferenced methods were removed from SubsystemContentHeader because it made it easier
to enforce invariants, etc.

A modification was made to the abstract SubsystemTest class to allow bundle file names to
be different from the symbolic name.

A few typos were corrected.

Added:
    aries/trunk/subsystem/subsystem-core/src/test/java/org/apache/aries/subsystem/core/archive/Aries1425Test.java
    aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/defect/Aries1425Test.java
Modified:
    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/SubsystemContentRequirement.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResource.java
    aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/SubsystemTest.java

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=1707428&r1=1707427&r2=1707428&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
Thu Oct  8 02:13:58 2015
@@ -20,6 +20,8 @@ import java.util.List;
 import org.apache.aries.subsystem.core.internal.ResourceHelper;
 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;
@@ -31,30 +33,37 @@ public class SubsystemContentHeader exte
 		public static final String DIRECTIVE_RESOLUTION = ResolutionDirective.NAME;
 		public static final String DIRECTIVE_STARTORDER = StartOrderDirective.NAME;
 		
+		private static final Collection<Parameter> defaultParameters = generateDefaultParameters(
+				// A default value for the type attribute is not included here
+				// because we need to determine in the constructor whether or 
+				// not it was specified as part of the original value.
+				// See ARIES-1425.
+				VersionRangeAttribute.DEFAULT_VERSION,
+				ResolutionDirective.MANDATORY,
+				// This is an implementation specific start-order directive
+				// value. The specification states there is no default value.
+				new StartOrderDirective("0"));
+		
+		// Was the type attribute specified as part of the original value?
+		private final boolean isTypeSpecified;
+		private final String originalValue;
+		
 		public Clause(String clause) {
 			super(
 					parsePath(clause, Patterns.SYMBOLIC_NAME, false), 
 					parseParameters(clause, true),
-					generateDefaultParameters(
-							TypeAttribute.DEFAULT,
-							VersionRangeAttribute.DEFAULT_VERSION,
-							ResolutionDirective.MANDATORY,
-							// This is an implementation specific start-order directive
-							// value. The specification states there is no default value.
-							new StartOrderDirective("0")));
-		}
-		
-		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));
+					defaultParameters);
+			if (parameters.get(TypeAttribute.NAME) == null) {
+				// The resource type was not specified.
+				isTypeSpecified = false;
+				// Add the default type.
+				parameters.put(TypeAttribute.NAME, TypeAttribute.DEFAULT);
+			}
+			else {
+				// The resource type was specified.
+				isTypeSpecified = true;
+			}
+			originalValue = clause;
 		}
 		
 		public String getSymbolicName() {
@@ -77,9 +86,18 @@ public class SubsystemContentHeader exte
 			return ((ResolutionDirective)getDirective(DIRECTIVE_RESOLUTION)).isMandatory();
 		}
 		
+		public boolean isTypeSpecified() {
+			return isTypeSpecified;
+		}
+		
 		public SubsystemContentRequirement toRequirement(Resource resource) {
 			return new SubsystemContentRequirement(this, resource);
 		}
+		
+		@Override
+	    public String toString() {
+	        return originalValue;
+	    }
 	}
 	
 	public static final String NAME = SubsystemConstants.SUBSYSTEM_CONTENT;
@@ -112,9 +130,7 @@ public class SubsystemContentHeader exte
 		return builder;
 	}
 	
-	public SubsystemContentHeader(Collection<Clause> clauses) {
-		super(clauses);
-	}
+	private final String originalValue;
 	
 	public SubsystemContentHeader(String value) {
 		super(
@@ -125,6 +141,7 @@ public class SubsystemContentHeader exte
 						return new Clause(clause);
 					}
 				});
+		originalValue = value;
 	}
 	
 	public boolean contains(Resource resource) {
@@ -132,16 +149,14 @@ public class SubsystemContentHeader exte
 	}
 	
 	public Clause getClause(Resource resource) {
-		String symbolicName = ResourceHelper.getSymbolicNameAttribute(resource);
-		Version version = ResourceHelper.getVersionAttribute(resource);
-		String type = ResourceHelper.getTypeAttribute(resource);
+		Capability capability = resource.getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE).get(0);
 		for (Clause clause : clauses) {
-			if (symbolicName.equals(clause.getPath())
-					&& clause.getVersionRange().includes(version)
-					&& type.equals(clause.getType()))
+			Requirement requirement = clause.toRequirement(resource);
+			if (ResourceHelper.matches(requirement, capability)) {
 				return clause;
+			}
 		}
-		return null;
+		return null;		
 	}
 	
 	public boolean isMandatory(Resource resource) {
@@ -158,7 +173,7 @@ public class SubsystemContentHeader exte
 
 	@Override
 	public String getValue() {
-		return toString();
+		return originalValue;
 	}
 
 	@Override
@@ -168,4 +183,9 @@ public class SubsystemContentHeader exte
 			requirements.add(clause.toRequirement(resource));
 		return requirements;
 	}
+	
+	@Override
+    public String toString() {
+        return originalValue;
+    }
 }

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemContentRequirement.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemContentRequirement.java?rev=1707428&r1=1707427&r2=1707428&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemContentRequirement.java
(original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemContentRequirement.java
Thu Oct  8 02:13:58 2015
@@ -33,8 +33,21 @@ public class SubsystemContentRequirement
 		StringBuilder builder = new StringBuilder("(&(")
 				.append(NAMESPACE).append('=')
 				.append(clause.getSymbolicName()).append(')');
-		for (Attribute attribute : clause.getAttributes())
-			attribute.appendToFilter(builder);
+		for (Attribute attribute : clause.getAttributes()) {
+			if (!clause.isTypeSpecified()
+					&& TypeAttribute.NAME.equals(attribute.getName())) {
+				// If the type attribute was not specified as part of the
+				// original clause, match against both bundles and fragments.
+				// See ARIES-1425.
+				builder.append("(|(").append(TypeAttribute.NAME).append('=')
+				.append(IdentityNamespace.TYPE_BUNDLE).append(")(")
+				.append(TypeAttribute.NAME).append('=').append(IdentityNamespace.TYPE_FRAGMENT)
+				.append("))");
+			}
+			else {
+				attribute.appendToFilter(builder);
+			}
+		}
 		directives.put(DIRECTIVE_FILTER, builder.append(')').toString());
 		this.resource = resource;
 	}

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=1707428&r1=1707427&r2=1707428&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
Thu Oct  8 02:13:58 2015
@@ -427,7 +427,7 @@ public class SubsystemResource implement
 	}
 
 	private ProvisionResourceHeader computeProvisionResourceHeader() {
-		Collection<Resource> dependencies = getDepedencies();
+		Collection<Resource> dependencies = getDependencies();
 		if (dependencies.isEmpty())
 			return null;
 		return ProvisionResourceHeader.newInstance(dependencies);
@@ -485,16 +485,27 @@ public class SubsystemResource implement
 				}
 			}
 		}
+		// First search the local repository.
 		map = resource.getLocalRepository().findProviders(Collections.singleton(requirement));
-		if (map.containsKey(requirement)) {
-			Collection<Capability> capabilities = map.get(requirement);
-			if (!capabilities.isEmpty())
-				return capabilities.iterator().next().getResource();
-		}
-		Collection<Capability> capabilities = new RepositoryServiceRepository().findProviders(requirement);
-		if (!capabilities.isEmpty())
-			return capabilities.iterator().next().getResource();
-		return null;
+		Collection<Capability> capabilities = map.get(requirement);
+		if (capabilities.isEmpty()) {
+			// Nothing found in the local repository so search the repository services.
+			capabilities = new RepositoryServiceRepository().findProviders(requirement);
+		}
+		if (capabilities.isEmpty()) {
+			// Nothing found period.
+			return null;
+		}
+		for (Capability capability : capabilities) {
+			if (!IdentityNamespace.TYPE_FRAGMENT.equals(
+					capability.getAttributes().get(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE))) {
+				// Favor the first resource that is not a fragment bundle.
+				// See ARIES-1425.
+				return capability.getResource();
+			}
+		}
+		// Nothing here but fragment bundles. Return the first one.
+		return capabilities.iterator().next().getResource();
 	}
 
 	private Resource findContent(DeployedContentHeader.Clause clause) throws BundleException,
IOException, InvalidSyntaxException, URISyntaxException {
@@ -540,7 +551,7 @@ public class SubsystemResource implement
 		return result;
 	}
 
-	private Collection<Resource> getDepedencies() {
+	private Collection<Resource> getDependencies() {
 		Collection<Resource> result = new ArrayList<Resource>(installableDependencies.size()
+ sharedDependencies.size());
 		result.addAll(installableDependencies);
 		result.addAll(sharedDependencies);

Added: aries/trunk/subsystem/subsystem-core/src/test/java/org/apache/aries/subsystem/core/archive/Aries1425Test.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/test/java/org/apache/aries/subsystem/core/archive/Aries1425Test.java?rev=1707428&view=auto
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/test/java/org/apache/aries/subsystem/core/archive/Aries1425Test.java
(added)
+++ aries/trunk/subsystem/subsystem-core/src/test/java/org/apache/aries/subsystem/core/archive/Aries1425Test.java
Thu Oct  8 02:13:58 2015
@@ -0,0 +1,195 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+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 org.apache.aries.subsystem.core.internal.OsgiIdentityCapability;
+import org.apache.aries.subsystem.core.internal.ResourceHelper;
+import org.junit.Test;
+import org.osgi.framework.Version;
+import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+
+/*
+ * https://issues.apache.org/jira/browse/ARIES-1425
+ * 
+ * Support both osgi.bundle and osgi.fragment resource types when given a 
+ * Subsystem-Content header clause with an unspecified type attribute.
+ */
+public class Aries1425Test {
+	private static final String BUNDLE_A = "bundle.a";
+	private static final String BUNDLE_B = "bundle.b;type=osgi.bundle";
+	private static final String BUNDLE_C = "bundle.c;type=osgi.fragment";
+	private static final String BUNDLE_D = "bundle.a;type=osgi.bundle";
+	private static final String BUNDLE_E = "bundle.b";
+	
+	private static final String HEADER_1 = BUNDLE_A + ',' + BUNDLE_B + ',' + BUNDLE_C;
+	private static final String HEADER_2 = BUNDLE_C + ',' + BUNDLE_D + ',' + BUNDLE_E;
+	
+	@Test
+	public void testGetValue() {
+		SubsystemContentHeader header = new SubsystemContentHeader(HEADER_1);
+		assertEquals("Wrong value", HEADER_1, header.getValue());
+	}
+	
+	@Test
+	public void testToString() {
+		SubsystemContentHeader header = new SubsystemContentHeader(HEADER_1);
+		assertEquals("Wrong value", HEADER_1, header.toString());
+	}
+	
+	@Test
+	public void testClauseToString() {
+		Set<String> clauseStrs = new HashSet<String>(Arrays.asList(HEADER_1.split(",")));
+		SubsystemContentHeader header = new SubsystemContentHeader(HEADER_1);
+		Collection<SubsystemContentHeader.Clause> clauses = header.getClauses();
+		assertEquals("Wrong size", 3, clauses.size());
+		for (SubsystemContentHeader.Clause clause : clauses) {
+			String clauseStr = clause.toString();
+			assertTrue("Wrong clause", clauseStrs.remove(clauseStr));
+		}
+	}
+	
+	@Test
+	public void testGetType() {
+		SubsystemContentHeader header = new SubsystemContentHeader(HEADER_1);
+		Collection<SubsystemContentHeader.Clause> clauses = header.getClauses();
+		assertEquals("Wrong size", 3, clauses.size());
+		Map<String, SubsystemContentHeader.Clause> map = new HashMap<String, SubsystemContentHeader.Clause>(3);
+		for (SubsystemContentHeader.Clause clause : clauses) {
+			map.put(clause.toString(), clause);
+		}
+		SubsystemContentHeader.Clause clause = map.get(BUNDLE_A);
+		assertEquals("Wrong type", IdentityNamespace.TYPE_BUNDLE, clause.getType());
+		clause = map.get(BUNDLE_B);
+		assertEquals("Wrong type", IdentityNamespace.TYPE_BUNDLE, clause.getType());
+		clause = map.get(BUNDLE_C);
+		assertEquals("Wrong type", IdentityNamespace.TYPE_FRAGMENT, clause.getType());
+	}
+	
+	@Test
+	public void testIsTypeSpecified() {
+		SubsystemContentHeader header = new SubsystemContentHeader(HEADER_1);
+		Collection<SubsystemContentHeader.Clause> clauses = header.getClauses();
+		assertEquals("Wrong size", 3, clauses.size());
+		Map<String, SubsystemContentHeader.Clause> map = new HashMap<String, SubsystemContentHeader.Clause>(3);
+		for (SubsystemContentHeader.Clause clause : clauses) {
+			map.put(clause.toString(), clause);
+		}
+		SubsystemContentHeader.Clause clause = map.get(BUNDLE_A);
+		assertEquals("Should not be specified", Boolean.FALSE, clause.isTypeSpecified());
+		clause = map.get(BUNDLE_B);
+		assertEquals("Should be specified", Boolean.TRUE, clause.isTypeSpecified());
+		clause = map.get(BUNDLE_C);
+		assertEquals("Should be specified", Boolean.TRUE, clause.isTypeSpecified());
+	}
+	
+	@Test
+	public void testToRequirement() {
+		SubsystemContentHeader header = new SubsystemContentHeader(HEADER_1);
+		Collection<SubsystemContentHeader.Clause> clauses = header.getClauses();
+		assertEquals("Wrong size", 3, clauses.size());
+		Map<String, SubsystemContentHeader.Clause> map = new HashMap<String, SubsystemContentHeader.Clause>(3);
+		for (SubsystemContentHeader.Clause clause : clauses) {
+			map.put(clause.toString(), clause);
+		}
+		Resource resource = new Resource() {
+			@Override
+			public List<Capability> getCapabilities(String namespace) {
+				return Collections.emptyList();
+			}
+
+			@Override
+			public List<Requirement> getRequirements(String namespace) {
+				return Collections.emptyList();
+			}
+		};
+		SubsystemContentHeader.Clause clause = map.get(BUNDLE_A);
+		Requirement requirement = clause.toRequirement(resource);
+		assertTrue("Wrong requirement", ResourceHelper.matches(
+				requirement, 
+				new OsgiIdentityCapability(
+						resource,
+						BUNDLE_A,
+						Version.emptyVersion,
+						IdentityNamespace.TYPE_FRAGMENT)));
+		assertTrue("Wrong requirement", ResourceHelper.matches(
+				requirement, 
+				new OsgiIdentityCapability(
+						resource,
+						BUNDLE_A,
+						Version.emptyVersion,
+						IdentityNamespace.TYPE_BUNDLE)));
+		clause = map.get(BUNDLE_B);
+		requirement = clause.toRequirement(resource);
+		assertFalse("Wrong requirement", ResourceHelper.matches(
+				requirement, 
+				new OsgiIdentityCapability(
+						resource,
+						"bundle.b",
+						Version.emptyVersion,
+						IdentityNamespace.TYPE_FRAGMENT)));
+		assertTrue("Wrong requirement", ResourceHelper.matches(
+				requirement, 
+				new OsgiIdentityCapability(
+						resource,
+						"bundle.b",
+						Version.emptyVersion,
+						IdentityNamespace.TYPE_BUNDLE)));
+		clause = map.get(BUNDLE_C);
+		requirement = clause.toRequirement(resource);
+		assertTrue("Wrong requirement", ResourceHelper.matches(
+				requirement, 
+				new OsgiIdentityCapability(
+						resource,
+						"bundle.c",
+						Version.emptyVersion,
+						IdentityNamespace.TYPE_FRAGMENT)));
+		assertFalse("Wrong requirement", ResourceHelper.matches(
+				requirement, 
+				new OsgiIdentityCapability(
+						resource,
+						"bundle.c",
+						Version.emptyVersion,
+						IdentityNamespace.TYPE_BUNDLE)));
+	}
+	
+	@Test
+	public void testEquals() {
+		SubsystemContentHeader header1 = new SubsystemContentHeader(HEADER_1);
+		SubsystemContentHeader header2 = new SubsystemContentHeader(HEADER_2);
+		assertEquals("Headers are equal", header1, header2);
+	}
+	
+	@Test
+	public void testHashcode() {
+		SubsystemContentHeader header1 = new SubsystemContentHeader(HEADER_1);
+		SubsystemContentHeader header2 = new SubsystemContentHeader(HEADER_2);
+		assertEquals("Headers are equal", header1.hashCode(), header2.hashCode());
+	}
+}

Modified: aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/SubsystemTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/SubsystemTest.java?rev=1707428&r1=1707427&r2=1707428&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/SubsystemTest.java
(original)
+++ aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/SubsystemTest.java
Thu Oct  8 02:13:58 2015
@@ -271,7 +271,7 @@ public abstract class SubsystemTest exte
 		assertConstituent(subsystem, symbolicName, version, IdentityNamespace.TYPE_BUNDLE);
 	}
 
-	protected void assertContituent(Subsystem subsystem, String symbolicName, String type) {
+	protected void assertConstituent(Subsystem subsystem, String symbolicName, String type)
{
 		assertConstituent(subsystem, symbolicName, Version.emptyVersion, type);
 	}
 
@@ -557,10 +557,13 @@ public abstract class SubsystemTest exte
 		}
 		createBundle(emptyFiles, headerMap);
 	}
+	
+	protected static void createBundle(List<String> emptyFiles, Map<String, String>
headers) throws IOException {
+		createBundle(headers.get(Constants.BUNDLE_SYMBOLICNAME), emptyFiles, headers);
+	}
 
-	private static void createBundle(List<String> emptyFiles, Map<String, String>
headers) throws IOException
+	protected static void createBundle(String fileName, List<String> emptyFiles, Map<String,
String> headers) throws IOException
 	{
-		String symbolicName = headers.get(Constants.BUNDLE_SYMBOLICNAME);
 		JarFixture bundle = ArchiveFixture.newJar();
 		ManifestFixture manifest = bundle.manifest();
 		for (Entry<String, String> header : headers.entrySet()) {
@@ -569,7 +572,7 @@ public abstract class SubsystemTest exte
 		for (String path : emptyFiles) {
 			bundle.file(path).end();
 		}
-		write(symbolicName, bundle);
+		write(fileName, bundle);
 	}
 
 	protected static void createBlueprintBundle(String symbolicName, String blueprintXml)

Added: aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/defect/Aries1425Test.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/defect/Aries1425Test.java?rev=1707428&view=auto
==============================================================================
--- aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/defect/Aries1425Test.java
(added)
+++ aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/defect/Aries1425Test.java
Thu Oct  8 02:13:58 2015
@@ -0,0 +1,287 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.itests.defect;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.aries.subsystem.core.archive.DeployedContentHeader;
+import org.apache.aries.subsystem.itests.SubsystemTest;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.service.subsystem.Subsystem;
+import org.osgi.service.subsystem.SubsystemConstants;
+import org.osgi.service.subsystem.SubsystemException;
+
+/*
+ * https://issues.apache.org/jira/browse/ARIES-1425
+ * 
+ * Support both osgi.bundle and osgi.fragment resource types when given a 
+ * Subsystem-Content header clause with an unspecified type attribute.
+ */
+public class Aries1425Test extends SubsystemTest {
+    /*
+     * Subsystem-SymbolicName: application.a.esa
+     * Subsystem-Content: bundle.a.jar, bundle.b.jar
+     * 
+	 * Included In Archive
+	 * 		bundle.a.fragment.jar
+	 * 		bundle.b.jar
+     */
+    private static final String APPLICATION_A = "application.a.esa";
+    /*
+     * Subsystem-SymbolicName: application.b.esa
+     * Subsystem-Content: bundle.a.jar
+     * 
+	 * Included In Archive
+	 * 		bundle.a.fragment.jar
+	 * 		bundle.a.bundle.jar
+     */
+    private static final String APPLICATION_B = "application.b.esa";
+    /*
+     * Subsystem-SymbolicName: application.c.esa
+     * Subsystem-Content: bundle.a.jar
+     */
+    private static final String APPLICATION_C = "application.c.esa";
+    /*
+     * Subsystem-SymbolicName: application.d.esa
+     * Subsystem-Content: bundle.a.jar, bundle.b.jar
+     * 
+     * Included In Archive
+	 * 		bundle.a.fragment.jar
+     */
+    private static final String APPLICATION_D = "application.d.esa";
+    
+    private static final String BUNDLE_A = "bundle.a.jar";
+	/*
+	 * Bundle-SymbolicName: bundle.a.jar
+	 * Fragment-Host: bundle.b.jar
+	 */
+	private static final String BUNDLE_A_FRAGMENT = "bundle.a.fragment.jar";
+	/*
+	 * Bundle-SymbolicName: bundle.a.jar
+	 */
+	private static final String BUNDLE_A_BUNDLE = "bundle.a.bundle.jar";
+	/*
+	 * Bundle-SymbolicName: bundle.b.jar
+	 */
+	private static final String BUNDLE_B = "bundle.b.jar";
+	
+	private static boolean createdTestFiles;
+	
+	@Before
+	public void createTestFiles() throws Exception {
+		if (createdTestFiles)
+			return;
+		createBundleABundle();
+		createBundleAFragment();
+		createBundleB();
+		createApplicationA();
+		createApplicationB();
+		createApplicationC();
+		createApplicationD();
+		createdTestFiles = true;
+	}
+	
+	private void createBundleABundle() throws IOException {
+		Map<String, String> headers = new HashMap<String, String>();
+		headers.put(Constants.BUNDLE_SYMBOLICNAME, BUNDLE_A);
+		createBundle(BUNDLE_A_BUNDLE, Collections.<String>emptyList(), headers);
+	}
+	
+	private void createBundleAFragment() throws IOException {
+		Map<String, String> headers = new HashMap<String, String>();
+		headers.put(Constants.BUNDLE_SYMBOLICNAME, BUNDLE_A);
+		headers.put(Constants.FRAGMENT_HOST, BUNDLE_B);
+		createBundle(BUNDLE_A_FRAGMENT, Collections.<String>emptyList(), headers);
+	}
+	
+	private void createBundleB() throws IOException {
+		createBundle(name(BUNDLE_B));
+	}
+	
+	private static void createApplicationA() throws IOException {
+        createApplicationAManifest();
+        createSubsystem(APPLICATION_A, BUNDLE_A_FRAGMENT, BUNDLE_B);
+    }
+    
+    private static void createApplicationAManifest() throws IOException {
+        Map<String, String> attributes = new HashMap<String, String>();
+        attributes.put(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME, APPLICATION_A);
+        attributes.put(SubsystemConstants.SUBSYSTEM_CONTENT, BUNDLE_A + ',' + BUNDLE_B);
+        createManifest(APPLICATION_A + ".mf", attributes);
+    }
+    
+    private static void createApplicationB() throws IOException {
+        createApplicationBManifest();
+        createSubsystem(APPLICATION_B, BUNDLE_A_FRAGMENT, BUNDLE_A_BUNDLE);
+    }
+    
+    private static void createApplicationBManifest() throws IOException {
+        Map<String, String> attributes = new HashMap<String, String>();
+        attributes.put(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME, APPLICATION_B);
+        attributes.put(SubsystemConstants.SUBSYSTEM_CONTENT, BUNDLE_A);
+        createManifest(APPLICATION_B + ".mf", attributes);
+    }
+    
+    private static void createApplicationC() throws IOException {
+        createApplicationCManifest();
+        createSubsystem(APPLICATION_C);
+    }
+    
+    private static void createApplicationCManifest() throws IOException {
+        Map<String, String> attributes = new HashMap<String, String>();
+        attributes.put(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME, APPLICATION_C);
+        attributes.put(SubsystemConstants.SUBSYSTEM_CONTENT, BUNDLE_A);
+        createManifest(APPLICATION_C + ".mf", attributes);
+    }
+    
+    private static void createApplicationD() throws IOException {
+        createApplicationDManifest();
+        createSubsystem(APPLICATION_D, BUNDLE_A_FRAGMENT);
+    }
+    
+    private static void createApplicationDManifest() throws IOException {
+        Map<String, String> attributes = new HashMap<String, String>();
+        attributes.put(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME, APPLICATION_D);
+        attributes.put(SubsystemConstants.SUBSYSTEM_CONTENT, BUNDLE_A);
+        createManifest(APPLICATION_D + ".mf", attributes);
+    }
+    
+    @Test
+    public void testFragmentSelected() throws Exception {
+    	try {
+    		Subsystem applicationA = installSubsystemFromFile(APPLICATION_A);
+    		try {
+    			assertConstituent(applicationA, BUNDLE_A, null, IdentityNamespace.TYPE_FRAGMENT);
+    		}
+    		finally {
+    			uninstallSubsystemSilently(applicationA);
+    		}
+    	}
+    	catch (SubsystemException e) {
+    		e.printStackTrace();
+    		fail("Subsystem should have installed");
+    	}
+    }
+    
+    @Test
+    public void testFragmentResolved() throws Exception {
+    	Subsystem applicationA = installSubsystemFromFile(APPLICATION_A);
+    	try {
+    		applicationA.start();
+    		try {
+    			Bundle bundleA = getConstituentAsBundle(applicationA, BUNDLE_A, null, IdentityNamespace.TYPE_FRAGMENT);
+    			assertBundleState(bundleA, Bundle.RESOLVED);
+    		}
+    		finally {
+    			stopSubsystemSilently(applicationA);
+    		}
+    	}
+    	finally {
+    		uninstallSubsystemSilently(applicationA);
+    	}
+    }
+    
+    @Test
+    public void testDeployedContentHeader() throws Exception {
+    	Subsystem applicationA = installSubsystemFromFile(APPLICATION_A);
+    	try {
+    		Map<String, String> headers = applicationA.getDeploymentHeaders();
+    		String header = headers.get(SubsystemConstants.DEPLOYED_CONTENT);
+			DeployedContentHeader dch = new DeployedContentHeader(header);
+			boolean foundClause = false;
+			for (DeployedContentHeader.Clause clause : dch.getClauses()) {
+				if (BUNDLE_A.equals(clause.getSymbolicName())) {
+					assertEquals("Wrong type", IdentityNamespace.TYPE_FRAGMENT, clause.getType());
+					foundClause = true;
+					break;
+				}
+			}
+			assertTrue("Missing clause", foundClause);
+    	}
+    	finally {
+    		uninstallSubsystemSilently(applicationA);
+    	}
+    }
+    
+    @Test
+    public void testProvisionResourceHeader() throws Exception {
+    	Subsystem applicationA = installSubsystemFromFile(APPLICATION_A);
+    	try {
+    		Map<String, String> headers = applicationA.getDeploymentHeaders();
+    		String header = headers.get(SubsystemConstants.PROVISION_RESOURCE);
+			assertFalse("Fragment content treated as dependency", header != null && header.contains(BUNDLE_A));
+    	}
+    	finally {
+    		uninstallSubsystemSilently(applicationA);
+    	}
+    }
+    
+    @Test
+    public void testBundleSelectedFromLocalRepository() throws Exception {
+    	Subsystem applicationB = installSubsystemFromFile(APPLICATION_B);
+    	try {
+    		assertNotConstituent(applicationB, BUNDLE_A, null, IdentityNamespace.TYPE_FRAGMENT);
+    		assertConstituent(applicationB, BUNDLE_A, null, IdentityNamespace.TYPE_BUNDLE);
+    	}
+    	finally {
+    		uninstallSubsystemSilently(applicationB);
+    	}
+    }
+    
+    @Test
+    public void testBundleSelectedFromRemoteRepository() throws Exception {
+    	// Make sure the repository containing the fragment comes first.
+    	registerRepositoryService(BUNDLE_A_FRAGMENT);
+    	registerRepositoryService(BUNDLE_A_BUNDLE);
+    	
+    	Subsystem applicationC = installSubsystemFromFile(APPLICATION_C);
+    	try {
+    		assertNotConstituent(applicationC, BUNDLE_A, null, IdentityNamespace.TYPE_FRAGMENT);
+    		assertConstituent(applicationC, BUNDLE_A, null, IdentityNamespace.TYPE_BUNDLE);
+    	}
+    	finally {
+    		uninstallSubsystemSilently(applicationC);
+    	}
+    }
+    
+    @Test
+    public void testFragmentFromLocalRepoSelectedBeforeBundleRemoteRepository() throws Exception
{
+    	registerRepositoryService(BUNDLE_A_BUNDLE, BUNDLE_B);
+    	Subsystem applicationD = installSubsystemFromFile(APPLICATION_D);
+    	try {
+    		assertNotConstituent(applicationD, BUNDLE_A, null, IdentityNamespace.TYPE_BUNDLE);
+    		assertConstituent(applicationD, BUNDLE_A, null, IdentityNamespace.TYPE_FRAGMENT);
+    	}
+    	finally {
+    		uninstallSubsystemSilently(applicationD);
+    	}
+    }
+}



Mime
View raw message