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/10 16:46:13 UTC

svn commit: r1242827 - in /aries/trunk/subsystem: subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/ subsystem-itests/src/test/resources/emptyFeature/OSGI-INF/ subsys...

Author: jwross
Date: Fri Feb 10 15:46:13 2012
New Revision: 1242827

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

(1) updated tests based on change to synchronous subsystem operations
(2) put back in root subsystem fail on stop
(3) added new empty feature test
(4) added new empty subsystem test
(5) start region context bundle persistently
(6) return default value for subsystem type and version if corresponding header is not present
(7) getConstituents should use the context of the region context bundle when iterating over the region's bundle ids, not the activator's bundle context
(8) uninstall region context bundle upon subsystem uninstall
(9) getBundleContext returns null if subsystem state in install_failed or uninstalled

Added:
    aries/trunk/subsystem/subsystem-itests/src/test/resources/emptySubsystem/
Modified:
    aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Activator.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/SubsystemTest.java
    aries/trunk/subsystem/subsystem-itests/src/test/resources/emptyFeature/OSGI-INF/SUBSYSTEM.MF
    aries/trunk/subsystem/subsystem-itests/src/test/resources/feature3/   (props changed)

Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Activator.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Activator.java?rev=1242827&r1=1242826&r2=1242827&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Activator.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Activator.java Fri Feb 10 15:46:13 2012
@@ -105,8 +105,7 @@ public class Activator implements Bundle
 	@Override
 	public synchronized void stop(BundleContext context) /*throws Exception*/ {
 		logger.debug(LOG_ENTRY, "stop", context);
-		root.stop();
-		registrar.unregisterAll();
+		root.stop0();
 		for (int i = registrations.size() - 1; i >= 0; i--) {
 			try {
 				registrations.get(i).unregister();

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=1242827&r1=1242826&r2=1242827&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 Fri Feb 10 15:46:13 2012
@@ -50,7 +50,6 @@ import org.apache.aries.subsystem.core.a
 import org.apache.aries.subsystem.core.archive.SubsystemArchive;
 import org.apache.aries.subsystem.core.archive.SubsystemManifest;
 import org.apache.aries.subsystem.core.archive.SubsystemSymbolicNameHeader;
-import org.apache.aries.subsystem.core.archive.VersionHeader;
 import org.apache.aries.subsystem.core.obr.SubsystemEnvironment;
 import org.apache.aries.subsystem.core.resource.SubsystemFileResource;
 import org.eclipse.equinox.region.Region;
@@ -342,6 +341,8 @@ public class AriesSubsystem implements S
 	
 	@Override
 	public BundleContext getBundleContext() {
+		if (EnumSet.of(State.INSTALL_FAILED, State.UNINSTALLED).contains(getState()))
+			return null;
 		return region.getBundle(RegionContextBundleHelper.SYMBOLICNAME_PREFIX + id, RegionContextBundleHelper.VERSION).getBundleContext();
 	}
 	
@@ -362,7 +363,7 @@ public class AriesSubsystem implements S
 		Collection<Resource> resources = new ArrayList<Resource>();
 		if (isRoot() || isApplication() || isComposite()) {
 			Set<Long> bundleIds = region.getBundleIds();
-			BundleContext context = Activator.getInstance().getBundleContext();
+			BundleContext context = getBundleContext();
 			for (Long bundleId : bundleIds)
 				resources.add(context.getBundle(bundleId).adapt(BundleRevision.class));
 		}
@@ -415,12 +416,18 @@ public class AriesSubsystem implements S
 	
 	@Override
 	public String getType() {
-		return getSubsystemHeaders(null).get(SubsystemConstants.SUBSYSTEM_TYPE);
+		String result = getSubsystemHeaders(null).get(SubsystemConstants.SUBSYSTEM_TYPE);
+		if (result == null)
+			result = SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION;
+		return result;
 	}
 
 	@Override
 	public Version getVersion() {
-		return ((VersionHeader)archive.getSubsystemManifest().getSubsystemVersion()).getVersion();
+		String version = getSubsystemHeaders(null).get(SubsystemConstants.SUBSYSTEM_VERSION);
+		if (version == null)
+			return Version.emptyVersion;
+		return Version.parseVersion(version);
 	}
 
 	@Override
@@ -550,34 +557,9 @@ public class AriesSubsystem implements S
 	 */
 	@Override
 	public synchronized void stop() throws SubsystemException {
-		if (getState() == State.UNINSTALLING || getState() == State.UNINSTALLED) {
-			throw new SubsystemException("Cannot stop from state " + getState());
-		}
-		else if (getState() == State.STARTING) {
-			waitForStateChange();
-			stop();
-		}
-		else if (getState() != State.ACTIVE) {
-			return;
-		}
-		setState(State.STOPPING);
-		for (Resource resource : constituents) {
-			try {
-				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?
-		setState(State.RESOLVED);
-//		try {
-//			persist(State.RESOLVED);
-//		}
-//		catch (IOException e) {
-//			throw new SubsystemException(e);
-//		}
+		// The root subsystem may not be stopped.
+		checkRoot();
+		stop0();
 	}
 	
 	/* INSTALLING	Wait, Uninstall
@@ -593,6 +575,7 @@ public class AriesSubsystem implements S
 	 */
 	@Override
 	public synchronized void uninstall() throws SubsystemException {
+		// The root subsystem may not be uninstalled.
 		checkRoot();
 		State state = getState();
 		if (state == State.UNINSTALLING || state == State.UNINSTALLED) {
@@ -624,6 +607,7 @@ public class AriesSubsystem implements S
 		deleteFile(directory);
 		setState(State.UNINSTALLED);
 		Activator.getInstance().getSubsystemServiceRegistrar().unregister(this);
+		RegionContextBundleHelper.uninstallRegionContextBundle(this);
 	}
 	
 	void bundleChanged(BundleEvent event) {
@@ -708,6 +692,31 @@ public class AriesSubsystem implements S
 			setState(State.INSTALLED);
 	}
 	
+	void stop0() {
+		if (getState() == State.UNINSTALLING || getState() == State.UNINSTALLED) {
+			throw new SubsystemException("Cannot stop from state " + getState());
+		}
+		else if (getState() == State.STARTING) {
+			waitForStateChange();
+			stop();
+		}
+		else if (getState() != State.ACTIVE) {
+			return;
+		}
+		setState(State.STOPPING);
+		for (Resource resource : constituents) {
+			try {
+				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?
+		setState(State.RESOLVED);
+	}
+	
 	protected boolean contains(Resource resource) {
 		return constituents.contains(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=1242827&r1=1242826&r2=1242827&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 Fri Feb 10 15:46:13 2012
@@ -34,7 +34,21 @@ public class RegionContextBundleHelper {
 			}
 			catch (BundleException e) {}
 		}
-		b.start(Bundle.START_TRANSIENT);
+		// The region context bundle must be started persistently.
+		b.start();
+	}
+	
+	public static void uninstallRegionContextBundle(AriesSubsystem subsystem) {
+		String symbolicName = SYMBOLICNAME_PREFIX + subsystem.getSubsystemId();
+		Bundle bundle = subsystem.getRegion().getBundle(symbolicName, VERSION);
+		if (bundle == null)
+			return;
+		try {
+			bundle.uninstall();
+		}
+		catch (BundleException e) {
+			// TODO Should we really eat this? At least log it?
+		}
 	}
 	
 	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=1242827&r1=1242826&r2=1242827&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 Fri Feb 10 15:46:13 2012
@@ -21,15 +21,60 @@ package org.apache.aries.subsystem.itest
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+
+import org.apache.aries.subsystem.itests.util.Utils;
+import org.apache.aries.unittest.fixture.ArchiveFixture;
+import org.apache.aries.unittest.fixture.ArchiveFixture.ZipFixture;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.ops4j.pax.exam.junit.JUnit4TestRunner;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
 import org.osgi.service.subsystem.Subsystem;
+import org.osgi.service.subsystem.SubsystemConstants;
 
 @RunWith(JUnit4TestRunner.class)
 public class BasicTest extends SubsystemTest {
+	private static void createApplication(String name, String[] content) throws Exception {
+		ZipFixture feature = ArchiveFixture
+				.newZip()
+				.binary("OSGI-INF/SUBSYSTEM.MF",
+						FeatureTest.class.getClassLoader().getResourceAsStream(
+								name + "/OSGI-INF/SUBSYSTEM.MF"));
+		for (String s : content) {
+			try {
+				feature.binary(s,
+						FeatureTest.class.getClassLoader().getResourceAsStream(
+								name + '/' + s));
+			}
+			catch (Exception e) {
+				feature.binary(s, new FileInputStream(new File(s)));
+			}
+		}
+		feature.end();
+		FileOutputStream fos = new FileOutputStream(name + ".ssa");
+		try {
+			feature.writeOut(fos);
+		} finally {
+			Utils.closeQuietly(fos);
+		}
+	}
+	
+	@Before
+	public static void createApplications() throws Exception {
+		if (createdApplications) {
+			return;
+		}
+		createApplication("emptyFeature", new String[]{});
+		createApplication("emptySubsystem", new String[]{});
+		createdApplications = true;
+	}
+	
 	/*
 	 * When the subsystems implementation bundle is installed, there should be
 	 * a Subsystem service available.
@@ -50,4 +95,70 @@ public class BasicTest extends Subsystem
     	Subsystem subsystem = bundleContext.getService(serviceReference);
     	assertNotNull("Subsystem service not found", subsystem);
     }
+    
+    @Test
+    public void testEmptyFeature() throws Exception {
+    	Subsystem emptyFeature = installSubsystemFromFile("emptyFeature.ssa");
+		AssertionError error = null;
+		try {
+			assertSymbolicName("org.apache.aries.subsystem.itests.feature.empty", emptyFeature);
+			assertVersion("1.1.2", emptyFeature);
+			assertType(SubsystemConstants.SUBSYSTEM_TYPE_FEATURE, emptyFeature);
+			assertConstituents(0, emptyFeature);
+			assertChildren(0, emptyFeature);
+			startSubsystem(emptyFeature);
+			stopSubsystem(emptyFeature);
+		}
+		catch (AssertionError e) {
+			error = e;
+			throw e;
+		}
+		finally {
+			try {
+				uninstallSubsystem(emptyFeature);
+			}
+			catch (AssertionError e) {
+				if (error == null)
+					throw e;
+				e.printStackTrace();
+			}
+		}
+    }
+    
+    /*
+     * This tests a subsystem containing only a subsystem manifest which, in
+     * turn, contains only a Subsystem-SymbolicName header.
+     */
+    @Test
+    public void testEmptySubsystem() throws Exception {
+    	Subsystem emptySubsystem = installSubsystemFromFile("emptySubsystem.ssa");
+		AssertionError error = null;
+		try {
+			assertSymbolicName("org.apache.aries.subsystem.itests.subsystem.empty", emptySubsystem);
+			// The version should be the default version.
+			assertVersion(Version.emptyVersion, emptySubsystem);
+			// The type should be the default type.
+			assertType(SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION, emptySubsystem);
+			// Since the default type is application, which is a scoped subsystem, there will
+			// be one constituent representing the region context bundle.
+			assertConstituents(1, emptySubsystem);
+			assertChildren(0, emptySubsystem);
+			startSubsystem(emptySubsystem);
+			stopSubsystem(emptySubsystem);
+		}
+		catch (AssertionError e) {
+			error = e;
+			throw e;
+		}
+		finally {
+			try {
+				uninstallSubsystem(emptySubsystem);
+			}
+			catch (AssertionError e) {
+				if (error == null)
+					throw e;
+				e.printStackTrace();
+			}
+		}
+    }
 }

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=1242827&r1=1242826&r2=1242827&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 Fri Feb 10 15:46:13 2012
@@ -319,9 +319,7 @@ public abstract class SubsystemTest exte
 	}
 	
 	protected void assertRegionContextBundle(Subsystem s) {
-		BundleContext bc = s.getBundleContext();
-		assertNotNull("No region context bundle", bc);
-		Bundle b = bc.getBundle();
+		Bundle b = getRegionContextBundle(s);
 		assertEquals("Not active", Bundle.ACTIVE, b.getState());
 		assertEquals("Wrong location", s.getLocation() + '/' + s.getSubsystemId(), b.getLocation());
 		assertEquals("Wrong symbolic name", "org.osgi.service.subsystem.region.context." + s.getSubsystemId(), b.getSymbolicName());
@@ -380,6 +378,10 @@ public abstract class SubsystemTest exte
 		assertEquals("Wrong symbolic name: " + subsystem.getSymbolicName(), expected, subsystem.getSymbolicName());
 	}
 	
+	protected void assertType(String expected, Subsystem subsystem) {
+		assertEquals("Wrong type", expected, subsystem.getType());
+	}
+	
 	protected void assertVersion(String expected, Subsystem subsystem) {
 		assertVersion(Version.parseVersion(expected), subsystem);
 	}
@@ -392,6 +394,12 @@ public abstract class SubsystemTest exte
 		assertEquals("Wrong version", expected, actual);
 	}
 	
+	protected Bundle getRegionContextBundle(Subsystem subsystem) {
+		BundleContext bc = subsystem.getBundleContext();
+		assertNotNull("No region context bundle", bc);
+		return bc.getBundle();
+	}
+	
 	protected Subsystem getRootSubsystem() {
 		return getOsgiService(Subsystem.class);
 	}
@@ -432,16 +440,15 @@ public abstract class SubsystemTest exte
 		subsystemEvents.clear();
 		Subsystem subsystem = getRootSubsystem().install(location, content);
 		assertSubsystemNotNull(subsystem);
-		assertEvent(subsystem, Subsystem.State.INSTALLING, subsystemEvents.poll(subsystem.getSubsystemId(), 5000));
-		assertEvent(subsystem, Subsystem.State.INSTALLED, subsystemEvents.poll(subsystem.getSubsystemId(), 5000));
+		assertEvent(subsystem, State.INSTALLING, 5000);
+		assertEvent(subsystem, State.INSTALLED, 5000);
 		assertChild(parent, subsystem);
 		assertLocation(location, subsystem);
 		assertParent(parent, subsystem);
-		assertState(EnumSet.of(State.INSTALLED, State.INSTALLING), subsystem);
+		assertState(State.INSTALLED, subsystem);
 		assertLocation(location, subsystem);
 		assertId(subsystem);
 		assertDirectory(subsystem);
-		assertState(State.INSTALLED, subsystem);
 		return subsystem;
 	}
 	
@@ -449,11 +456,10 @@ public abstract class SubsystemTest exte
 		assertState(State.INSTALLED, subsystem);
 		subsystemEvents.clear();
 		subsystem.start();
-		assertState(EnumSet.of(State.RESOLVING, State.RESOLVED, State.STARTING, State.ACTIVE), subsystem);
-		assertEvent(subsystem, Subsystem.State.RESOLVING, subsystemEvents.poll(subsystem.getSubsystemId(), 5000));
-		assertEvent(subsystem, Subsystem.State.RESOLVED, subsystemEvents.poll(subsystem.getSubsystemId(), 5000));
-		assertEvent(subsystem, Subsystem.State.STARTING, subsystemEvents.poll(subsystem.getSubsystemId(), 5000));
-		assertEvent(subsystem, Subsystem.State.ACTIVE, subsystemEvents.poll(subsystem.getSubsystemId(), 5000));
+		assertEvent(subsystem, State.RESOLVING, 5000);
+		assertEvent(subsystem, State.RESOLVED, 5000);
+		assertEvent(subsystem, State.STARTING, 5000);
+		assertEvent(subsystem, State.ACTIVE, 5000);
 		assertState(State.ACTIVE, subsystem);
 	}
 	
@@ -461,9 +467,8 @@ public abstract class SubsystemTest exte
 		assertState(State.ACTIVE, subsystem);
 		subsystemEvents.clear();
 		subsystem.stop();
-		assertState(EnumSet.of(State.STOPPING, State.RESOLVED), subsystem);
-		assertEvent(subsystem, Subsystem.State.STOPPING, subsystemEvents.poll(subsystem.getSubsystemId(), 5000));
-		assertEvent(subsystem, Subsystem.State.RESOLVED, subsystemEvents.poll(subsystem.getSubsystemId(), 5000));
+		assertEvent(subsystem, State.STOPPING, 5000);
+		assertEvent(subsystem, State.RESOLVED, 5000);
 		assertState(State.RESOLVED, subsystem);
 	}
 	
@@ -471,12 +476,12 @@ public abstract class SubsystemTest exte
 		assertState(EnumSet.of(State.INSTALLED, State.RESOLVED), subsystem);
 		subsystemEvents.clear();
 		Collection<Subsystem> parents = subsystem.getParents();
+		Bundle b = getRegionContextBundle(subsystem);
 		subsystem.uninstall();
-		assertState(EnumSet.of(State.UNINSTALLED, State.UNINSTALLING), subsystem);
-		assertEvent(subsystem, Subsystem.State.UNINSTALLING, subsystemEvents.poll(subsystem.getSubsystemId(), 5000));
-		assertEvent(subsystem, Subsystem.State.UNINSTALLED, subsystemEvents.poll(subsystem.getSubsystemId(), 5000));
+		assertEvent(subsystem, State.UNINSTALLING, 5000);
+		assertEvent(subsystem, State.UNINSTALLED, 5000);
 		assertState(State.UNINSTALLED, subsystem);
-		assertConstituents(0, subsystem);
+		assertEquals("Region context bundle not uninstalled", Bundle.UNINSTALLED, b.getState());
 		for (Subsystem parent : parents)
 			assertNotChild(parent, subsystem);
 		assertNotDirectory(subsystem);

Modified: aries/trunk/subsystem/subsystem-itests/src/test/resources/emptyFeature/OSGI-INF/SUBSYSTEM.MF
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-itests/src/test/resources/emptyFeature/OSGI-INF/SUBSYSTEM.MF?rev=1242827&r1=1242826&r2=1242827&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-itests/src/test/resources/emptyFeature/OSGI-INF/SUBSYSTEM.MF (original)
+++ aries/trunk/subsystem/subsystem-itests/src/test/resources/emptyFeature/OSGI-INF/SUBSYSTEM.MF Fri Feb 10 15:46:13 2012
@@ -1,5 +1 @@
-Manifest-Version: 2.0
-Subsystem-ManifestVersion: 1.0
-Subsystem-SymbolicName: org.apache.aries.subsystem.itests.feature.empty
-Subsystem-Version: 1.1.2
-Subsystem-Type: osgi.feature
\ No newline at end of file
+Subsystem-SymbolicName: org.apache.aries.subsystem.itests.subsystem.empty
\ No newline at end of file

Propchange: aries/trunk/subsystem/subsystem-itests/src/test/resources/feature3/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Fri Feb 10 15:46:13 2012
@@ -0,0 +1 @@
+tb3.jar