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/14 13:58:58 UTC

svn commit: r1243908 - 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: Tue Feb 14 12:58:58 2012
New Revision: 1243908

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

(1) added toString() in AbstractHeader
(2) fixed issue where Subsystem-Content manifest header was not being derived when subsystem has manifest with no content header
(3) fixed issue where feature constituents were being assigned to the scoped subsystem within the same region
(4) fixed issue where region context bundles were being generated for features
(5) fixed NPE issue in getBundleContext() for features
(6) fixed issue with generation of unique location when installing bundle resources
(7) now supports resource type osgi.fragment on subsystem lifecycle operations
(8) fixed issue where already started bundles were being called with start(START_TRANSIENT)
(9) root subsystem will now only stop child subsystems
(10) child subsystems should be stopped before any other constituents for all subsystems

Modified:
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/AbstractHeader.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/AriesSubsystem.java
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/RegionContextBundleHelper.java
    aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/BasicTest.java
    aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/FeatureTest.java
    aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/InstallTest.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/AbstractHeader.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/AbstractHeader.java?rev=1243908&r1=1243907&r2=1243908&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/AbstractHeader.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/AbstractHeader.java Tue Feb 14 12:58:58 2012
@@ -70,4 +70,13 @@ public abstract class AbstractHeader imp
 	public String getValue() {
 		return value;
 	}
+	
+	public String toString() {
+		return new StringBuilder(getClass().getName())
+		.append(": name=")
+		.append(name)
+		.append(", value=")
+		.append(value)
+		.toString();
+	}
 }

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=1243908&r1=1243907&r2=1243908&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 14 12:58:58 2012
@@ -273,8 +273,7 @@ public class AriesSubsystem implements S
 			}
 			// TODO Escaping 'this' reference.
 			s.add(this);
-			// TODO What the heck is going on here? Don't we need to add the bundle revision
-			// as a constituent as well?
+			constituents.add(br);
 		}
 		// TODO End proof of concept.
 		LOGGER.debug(LOG_EXIT, "init");
@@ -312,17 +311,17 @@ public class AriesSubsystem implements S
 			throw new SubsystemException(e);
 		}
 		environment = new SubsystemEnvironment(this);
-		if (archive.getSubsystemManifest() == null) {
-			// TODO Since it's optional to use the subsystem URI, it might be
-			// better to create the URI in a try/catch block and throw an
-			// exception with a message indicating we received a subsystem
-			// with no manifest and no subsystem URI.
-			archive.setSubsystemManifest(new SubsystemManifest(
-					uri.getSymbolicName(), 
-					uri.getVersion(), 
-					archive.getResources()));
-		}
-		region = createRegion(getSymbolicName() + ';' + getVersion() + ';' + getType() + ';' + getSubsystemId());
+		// Make sure the relevant headers are derived, if absent.
+		archive.setSubsystemManifest(new SubsystemManifest(
+				archive.getSubsystemManifest(),
+				uri == null ? null : uri.getSymbolicName(), 
+				uri == null ? null : uri.getVersion(), 
+				archive.getResources()));
+		// Unscoped subsystems don't get their own region. They share the region with their scoped parent.
+		if (isFeature())
+			region = parents.get(0).region;
+		else
+			region = createRegion(getSymbolicName() + ';' + getVersion() + ';' + getType() + ';' + getSubsystemId());
 	}
 	
 	public AriesSubsystem(SubsystemArchive archive, AriesSubsystem parent) throws Exception {
@@ -338,7 +337,11 @@ public class AriesSubsystem implements S
 		directory = new File(parent.directory, directoryName);
 		environment = new SubsystemEnvironment(this);
 		parents.add(parent);
-		region = createRegion(getSymbolicName() + ';' + getVersion() + ';' + getType() + ';' + getSubsystemId());
+		// Unscoped subsystems don't get their own region. They share the region with their scoped parent.
+		if (isFeature())
+			region = parents.get(0).region;
+		else
+			region = createRegion(getSymbolicName() + ';' + getVersion() + ';' + getType() + ';' + getSubsystemId());
 	}
 	
 	public SubsystemArchive getArchive() {
@@ -349,6 +352,10 @@ public class AriesSubsystem implements S
 	public BundleContext getBundleContext() {
 		if (EnumSet.of(State.INSTALL_FAILED, State.UNINSTALLED).contains(getState()))
 			return null;
+		// Features, and unscoped subsystems in general, do not have their own region context
+		// bundle but rather share with the scoped subsystem in the same region.
+		if (isFeature())
+			return parents.get(0).getBundleContext();
 		return region.getBundle(RegionContextBundleHelper.SYMBOLICNAME_PREFIX + id, RegionContextBundleHelper.VERSION).getBundleContext();
 	}
 	
@@ -366,15 +373,7 @@ public class AriesSubsystem implements S
 
 	@Override
 	public synchronized Collection<Resource> getConstituents() {
-		Collection<Resource> resources = new HashSet<Resource>();
-		if (isRoot() || isApplication() || isComposite()) {
-			Set<Long> bundleIds = region.getBundleIds();
-			BundleContext context = getBundleContext();
-			for (Long bundleId : bundleIds)
-				resources.add(context.getBundle(bundleId).adapt(BundleRevision.class));
-		}
-		resources.addAll(constituents);
-		return Collections.unmodifiableCollection(resources);
+		return Collections.unmodifiableCollection(constituents);
 	}
 
 	@Override
@@ -548,7 +547,7 @@ public class AriesSubsystem implements S
 				coordination.end();
 			} catch (CoordinationException e) {
 				LOGGER.error(
-						"An error occurred while starting in a resource in subsystem "
+						"An error occurred while starting a resource in subsystem "
 								+ this, e);
 				setState(State.RESOLVED);
 			}
@@ -619,7 +618,8 @@ public class AriesSubsystem implements S
 		deleteFile(directory);
 		setState(State.UNINSTALLED);
 		Activator.getInstance().getSubsystemServiceRegistrar().unregister(this);
-		RegionContextBundleHelper.uninstallRegionContextBundle(this);
+		if (!isFeature())
+			constituents.remove(RegionContextBundleHelper.uninstallRegionContextBundle(this));
 	}
 	
 	void bundleChanged(BundleEvent event) {
@@ -650,7 +650,8 @@ public class AriesSubsystem implements S
 	}
 	
 	synchronized void install() throws Exception {
-		RegionContextBundleHelper.installRegionContextBundle(this);
+		if (!isFeature())
+			constituents.add(RegionContextBundleHelper.installRegionContextBundle(this));
 		Activator.getInstance().getSubsystemServiceRegistrar().register(this);
 		List<Resource> contentResources = new ArrayList<Resource>();
 		List<Resource> transitiveDependencies = new ArrayList<Resource>();
@@ -717,13 +718,29 @@ public class AriesSubsystem implements S
 			return;
 		}
 		setState(State.STOPPING);
-		for (Resource resource : constituents) {
+		// Stop child subsystems first.
+		for (AriesSubsystem subsystem : children) {
 			try {
-				stopResource(resource);
-			} catch (Exception e) {
+				stopResource(subsystem);
+			}
+			catch (Exception e) {
 				LOGGER.error("An error occurred while stopping resource "
-						+ resource + " of subsystem " + this, e);
-				// TODO Should FAILED go out for each failure?
+						+ subsystem + " of subsystem " + this, e);
+			}
+		}
+		// For non-root subsystems, stop any remaining constituents.
+		if (!isRoot()){
+			for (Resource resource : constituents) {
+				try {
+					// Don't stop the region context bundle.
+					if (ResourceHelper.getSymbolicNameAttribute(resource).startsWith(RegionContextBundleHelper.SYMBOLICNAME_PREFIX))
+						continue;
+					stopResource(resource);
+				} catch (Exception e) {
+					LOGGER.error("An error occurred while stopping resource "
+							+ resource + " of subsystem " + this, e);
+					// TODO Should FAILED go out for each failure?
+				}
 			}
 		}
 		// TODO Can we automatically assume it actually is resolved?
@@ -823,11 +840,6 @@ public class AriesSubsystem implements S
 			while (!provisionTo.parents.isEmpty())
 				provisionTo = provisionTo.parents.get(0);
 		}
-		else {
-			while (provisionTo.isFeature())
-				// Feature resources should be provisioned into the first parent that's not a feature.
-				provisionTo = provisionTo.parents.get(0);
-		}
 		return provisionTo;
 	}
 
@@ -842,7 +854,7 @@ public class AriesSubsystem implements S
 			}
 			else {
 				InputStream content = ((RepositoryContent)resource).getContent();
-				String location = provisionTo.getSubsystemId() + '@' + provisionTo.getSymbolicName() + '@' + content;
+				String location = provisionTo.getSubsystemId() + "@" + provisionTo.getSymbolicName() + "@" + ResourceHelper.getSymbolicNameAttribute(resource);
 				Bundle bundle = provisionTo.region.installBundle(location, content);
 				revision = bundle.adapt(BundleRevision.class);
 			}
@@ -854,15 +866,18 @@ public class AriesSubsystem implements S
 				resourceToSubsystems.put(revision, subsystems);
 			}
 			subsystems.add(this);
+			
 		}
 		final AriesSubsystem constituentOf = getConstituentOf(resource, provisionTo, transitive);
+		constituentOf.constituents.add(revision);
 		coordination.addParticipant(new Participant() {
 			public void ended(Coordination coordination) throws Exception {
-				constituentOf.constituents.add(revision);
+				// noop
 			}
 	
 			public void failed(Coordination coordination) throws Exception {
 				synchronized (resourceToSubsystems) {
+					constituentOf.constituents.remove(revision);
 					Set<AriesSubsystem> subsystems = resourceToSubsystems.get(revision);
 					subsystems.remove(AriesSubsystem.this);
 					if (subsystems.isEmpty()) {
@@ -880,6 +895,8 @@ public class AriesSubsystem implements S
 			installSubsystemResource(resource, coordination, transitive);
 		else if (ResourceConstants.IDENTITY_TYPE_BUNDLE.equals(type))
 			installBundleResource(resource, coordination, transitive);
+		else if (ResourceConstants.IDENTITY_TYPE_FRAGMENT.equals(type))
+			installBundleResource(resource, coordination, transitive);
 		else
 			throw new SubsystemException("Unsupported resource type: " + type);
 	}
@@ -986,6 +1003,8 @@ public class AriesSubsystem implements S
 
 	private void startBundleResource(Resource resource, Coordination coordination) throws BundleException {
 		final Bundle bundle = ((BundleRevision)resource).getBundle();
+		if ((bundle.getState() & (Bundle.STARTING | Bundle.ACTIVE)) != 0)
+			return;
 		bundle.start(Bundle.START_TRANSIENT);
 		if (coordination == null)
 			return;
@@ -1003,10 +1022,13 @@ public class AriesSubsystem implements S
 	private void startResource(Resource resource, Coordination coordination) throws BundleException, IOException {
 		String type = ResourceHelper.getTypeAttribute(resource);
 		// TODO Add to constants.
-		if ("osgi.subsystem".equals(type))
+		if (SubsystemConstants.IDENTITY_TYPE_SUBSYSTEM.equals(type))
 			startSubsystemResource(resource, coordination);
 		else if (ResourceConstants.IDENTITY_TYPE_BUNDLE.equals(type))
 			startBundleResource(resource, coordination);
+		else if (ResourceConstants.IDENTITY_TYPE_FRAGMENT.equals(type)) {
+			// Fragments are not started.
+		}
 		else
 			throw new SubsystemException("Unsupported resource type: " + type);
 	}
@@ -1034,7 +1056,7 @@ public class AriesSubsystem implements S
 	private void stopResource(Resource resource) throws BundleException, IOException {
 		String type = ResourceHelper.getTypeAttribute(resource);
 		// TODO Add to constants.
-		if ("osgi.subsystem".equals(type))
+		if (SubsystemConstants.IDENTITY_TYPE_SUBSYSTEM.equals(type))
 			stopSubsystemResource(resource);
 		else if (ResourceConstants.IDENTITY_TYPE_BUNDLE.equals(type))
 			stopBundleResource(resource);

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/RegionContextBundleHelper.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/RegionContextBundleHelper.java?rev=1243908&r1=1243907&r2=1243908&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/RegionContextBundleHelper.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/RegionContextBundleHelper.java Tue Feb 14 12:58:58 2012
@@ -12,17 +12,18 @@ import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleException;
 import org.osgi.framework.Constants;
 import org.osgi.framework.Version;
+import org.osgi.framework.wiring.BundleRevision;
 
 public class RegionContextBundleHelper {
 	public static final String SYMBOLICNAME_PREFIX = "org.osgi.service.subsystem.region.context.";
 	public static final Version VERSION = Version.parseVersion("1.0.0");
 	
-	public static void installRegionContextBundle(AriesSubsystem subsystem) throws BundleException, IOException {
+	public static BundleRevision installRegionContextBundle(AriesSubsystem subsystem) throws BundleException, IOException {
 		String symbolicName = SYMBOLICNAME_PREFIX + subsystem.getSubsystemId();
 		String location = subsystem.getLocation() + '/' + subsystem.getSubsystemId();
 		Bundle b = subsystem.getRegion().getBundle(symbolicName, VERSION);
 		if (b != null)
-			return;
+			return b.adapt(BundleRevision.class);
 		Bundle t = subsystem.getRegion().installBundle(location + "/temp", createTempBundle(symbolicName));
 		try {
 			t.start();
@@ -36,19 +37,21 @@ public class RegionContextBundleHelper {
 		}
 		// The region context bundle must be started persistently.
 		b.start();
+		return b.adapt(BundleRevision.class);
 	}
 	
-	public static void uninstallRegionContextBundle(AriesSubsystem subsystem) {
+	public static BundleRevision uninstallRegionContextBundle(AriesSubsystem subsystem) {
 		String symbolicName = SYMBOLICNAME_PREFIX + subsystem.getSubsystemId();
 		Bundle bundle = subsystem.getRegion().getBundle(symbolicName, VERSION);
 		if (bundle == null)
-			return;
+			throw new IllegalStateException("Missing region context bundle: " + symbolicName);
 		try {
 			bundle.uninstall();
 		}
 		catch (BundleException e) {
 			// TODO Should we really eat this? At least log it?
 		}
+		return bundle.adapt(BundleRevision.class);
 	}
 	
 	private static InputStream createRegionContextBundle(String symbolicName) throws IOException {

Modified: aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/BasicTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/BasicTest.java?rev=1243908&r1=1243907&r2=1243908&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/BasicTest.java (original)
+++ aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/BasicTest.java Tue Feb 14 12:58:58 2012
@@ -115,7 +115,7 @@ public class BasicTest extends Subsystem
 		}
 		finally {
 			try {
-				uninstallSubsystem(emptyFeature);
+				uninstallUnscopedSubsystem(emptyFeature);
 			}
 			catch (AssertionError e) {
 				if (error == null)
@@ -152,7 +152,7 @@ public class BasicTest extends Subsystem
 		}
 		finally {
 			try {
-				uninstallSubsystem(emptySubsystem);
+				uninstallScopedSubsystem(emptySubsystem);
 			}
 			catch (AssertionError e) {
 				if (error == null)

Modified: aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/FeatureTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/FeatureTest.java?rev=1243908&r1=1243907&r2=1243908&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/FeatureTest.java (original)
+++ aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/FeatureTest.java Tue Feb 14 12:58:58 2012
@@ -112,7 +112,7 @@ public class FeatureTest extends Subsyst
 		}
 		finally {
 			try {
-				uninstallSubsystem(feature1);
+				uninstallUnscopedSubsystem(feature1);
 				if (feature2 != null) {
 					assertEvent(feature2, Subsystem.State.UNINSTALLING, 5000);
 					assertEvent(feature2, Subsystem.State.UNINSTALLED, 5000);
@@ -135,7 +135,7 @@ public class FeatureTest extends Subsyst
 		try {
 			assertFeature3(feature3Before);
 			// Uninstall then reinstall the subsystem for a more robust test of the subsystem ID persistence.
-			uninstallSubsystem(feature3Before);
+			uninstallUnscopedSubsystem(feature3Before);
 			feature3Before = installSubsystemFromFile("feature3.ssa");
 			assertLastId(2);
 			assertFeature3(feature3Before);
@@ -156,7 +156,7 @@ public class FeatureTest extends Subsyst
 			try {
 				if (feature3After != null) {
 					stopSubsystem(feature3After);
-					uninstallSubsystem(feature3After);
+					uninstallUnscopedSubsystem(feature3After);
 				}
 			}
 			catch (AssertionError e) {
@@ -178,7 +178,7 @@ public class FeatureTest extends Subsyst
 			while (!feature2.getState().equals(Subsystem.State.INSTALLED))
 				Thread.sleep(100);
 			assertConstituent(feature2, "org.apache.aries.subsystem.itests.tb3", Version.parseVersion("1.0.0"), ResourceConstants.IDENTITY_TYPE_BUNDLE);
-			uninstallSubsystem(feature2);
+			uninstallUnscopedSubsystem(feature2);
 			assertNotChild(feature1, feature2);
 			assertConstituent(feature1, "org.apache.aries.subsystem.itests.tb3", Version.parseVersion("1.0.0"), ResourceConstants.IDENTITY_TYPE_BUNDLE);
 		}
@@ -188,7 +188,7 @@ public class FeatureTest extends Subsyst
 		}
 		finally {
 			try {
-				uninstallSubsystem(feature1);
+				uninstallUnscopedSubsystem(feature1);
 			}
 			catch (AssertionError e) {
 				if (error == null)

Modified: aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/InstallTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/InstallTest.java?rev=1243908&r1=1243907&r2=1243908&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/InstallTest.java (original)
+++ aries/trunk/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/InstallTest.java Tue Feb 14 12:58:58 2012
@@ -77,7 +77,7 @@ public class InstallTest extends Subsyst
 			assertSame(subsystem1, subsystem2);
 		}
 		finally {
-			uninstallSubsystem(subsystem1);
+			uninstallUnscopedSubsystem(subsystem1);
 		}
 	}
 }

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=1243908&r1=1243907&r2=1243908&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 Tue Feb 14 12:58:58 2012
@@ -494,18 +494,26 @@ public abstract class SubsystemTest exte
 		assertState(State.RESOLVED, subsystem);
 	}
 	
+	protected void uninstallScopedSubsystem(Subsystem subsystem) throws Exception {
+		Bundle b = getRegionContextBundle(subsystem);
+		uninstallSubsystem(subsystem);
+		assertEquals("Region context bundle not uninstalled", Bundle.UNINSTALLED, b.getState());
+	}
+	
 	protected void uninstallSubsystem(Subsystem subsystem) throws Exception {
 		assertState(EnumSet.of(State.INSTALLED, State.RESOLVED), subsystem);
 		subsystemEvents.clear();
 		Collection<Subsystem> parents = subsystem.getParents();
-		Bundle b = getRegionContextBundle(subsystem);
 		subsystem.uninstall();
 		assertEvent(subsystem, State.UNINSTALLING, 5000);
 		assertEvent(subsystem, State.UNINSTALLED, 5000);
 		assertState(State.UNINSTALLED, subsystem);
-		assertEquals("Region context bundle not uninstalled", Bundle.UNINSTALLED, b.getState());
 		for (Subsystem parent : parents)
 			assertNotChild(parent, subsystem);
 		assertNotDirectory(subsystem);
 	}
+	
+	protected void uninstallUnscopedSubsystem(Subsystem subsystem) throws Exception {
+		uninstallSubsystem(subsystem);
+	}
 }