/* * 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.itests; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.eclipse.equinox.region.Region; import org.eclipse.equinox.region.RegionDigraph; import org.eclipse.equinox.region.RegionFilter; import org.junit.Test; import org.osgi.framework.Bundle; import org.osgi.framework.BundleException; import org.osgi.framework.ServiceEvent; import org.osgi.framework.Version; import org.osgi.service.subsystem.Subsystem; import org.osgi.service.subsystem.SubsystemConstants; public class RootSubsystemTest extends SubsystemTest { /* * Subsystem-SymbolicName: application.a.esa * Subsystem-Content: bundle.a.jar */ private static final String APPLICATION_A = "application.a.esa"; /* * Bundle-SymbolicName: bundle.a.jar * Import-Package: org.osgi.framework */ private static final String BUNDLE_A = "bundle.a.jar"; @Override public void createApplications() throws Exception { createBundleA(); createApplicationA(); } private static void createApplicationA() throws IOException { createApplicationAManifest(); createSubsystem(APPLICATION_A, BUNDLE_A); } private static void createApplicationAManifest() throws IOException { Map<String, String> attributes = new HashMap<String, String>(); attributes.put(SubsystemConstants.SUBSYSTEM_SYMBOLICNAME, APPLICATION_A); createManifest(APPLICATION_A + ".mf", attributes); } private void createBundleA() throws IOException { createBundle(name(BUNDLE_A), importPackage("org.osgi.framework")); } // TODO Test root subsystem headers. @Test public void testDoNotStartExtraneousRootRegionBundles() throws Exception { bundleContext.installBundle(new File(BUNDLE_A).toURI().toURL().toString()); getSubsystemCoreBundle().stop(); getSubsystemCoreBundle().start(); Bundle bundleA = context().getBundleByName(BUNDLE_A); assertTrue("Extraneous root region bundle should not be started", (bundleA.getState() & (Bundle.INSTALLED | Bundle.RESOLVED)) != 0); } @Test public void testId() { assertEquals("Wrong root ID", getRootSubsystem().getSubsystemId(), 0); } @Test public void testLocation() { assertEquals("Wrong root location", getRootSubsystem().getLocation(), "subsystem://?Subsystem-SymbolicName=org.osgi.service.subsystem.root&Subsystem-Version=1.0.0"); } @Test public void testRegionContextBundle() throws BundleException { assertRegionContextBundle(getRootSubsystem()); getSubsystemCoreBundle().stop(); getSubsystemCoreBundle().start(); assertRegionContextBundle(getRootSubsystem()); } @Test public void testServiceEvents() throws Exception { Subsystem root = getRootSubsystem(); Bundle core = getSubsystemCoreBundle(); // TODO Temporary(?) workaround to allow time for any tardy service // events to arrive so they can be cleared. So far, this sleep has only // been necessary on the IBM 6.0 64-bit JDK. Thread.sleep(1000); subsystemEvents.clear(); core.stop(); assertServiceEventsStop(root); core.uninstall(); core = bundleContext.installBundle(normalizeBundleLocation(core)); core.start(); // There should be install events since the persisted root subsystem was // deleted when the subsystems implementation bundle was uninstalled. assertServiceEventsInstall(root); assertServiceEventsResolve(root); assertServiceEventsStart(root); core.stop(); assertServiceEventsStop(root); core.start(); // There should be no install events or RESOLVING event since there // should be a persisted root subsystem already in the RESOLVED state. assertServiceEventResolved(root, ServiceEvent.REGISTERED); assertServiceEventsStart(root); } @Test public void testSymbolicName() { assertEquals("Wrong root symbolic name", getRootSubsystem().getSymbolicName(), "org.osgi.service.subsystem.root"); } @Test public void testUninstallRootRegionBundleWithNoBundleEventHook() throws Exception { // Install an extraneous bundle into the root region. The bundle will // be recorded in the root subsystem's persistent memory. Bundle bundleA = bundleContext.installBundle(new File(BUNDLE_A).toURI().toURL().toString()); try { Bundle core = getSubsystemCoreBundle(); // Stop the subsystems bundle in order to unregister the bundle // event hook. core.stop(); // Uninstall the bundle so it won't be there on restart. bundleA.uninstall(); try { // Start the subsystems bundle and ensure the root subsystem // recovers from the uninstalled bundle being in persistent // memory. core.start(); } catch (BundleException e) { fail("Could not start subsystems bundle after uninstalling a root region bundle with no bundle event hook registered"); } } finally { if (Bundle.UNINSTALLED != bundleA.getState()) bundleA.uninstall(); } } @Test public void testVersion() { assertEquals("Wrong root version", getRootSubsystem().getVersion(), Version.parseVersion("1.0.0")); } /* * The root subsystem should be associated with the region in which the * subsystems implementation bundle is installed. */ @Test public void testRegion() throws Exception { RegionDigraph digraph = context().getService(RegionDigraph.class); Bundle core = getSubsystemCoreBundle(); Region kernel = digraph.getRegion(core); Subsystem root = getRootSubsystem(); Bundle rootRegionContext = root.getBundleContext().getBundle(); // Get the region containing the subsystem's region context bundle, // which is the same thing as getting the region with which the // subsystem is associated. Region region = digraph.getRegion(root.getBundleContext().getBundle()); assertEquals("Wrong region", kernel, region); // Uninstall the core bundle to remove the persisted root subsystem. core.uninstall(); // Clean up the lingering region context bundle. rootRegionContext.uninstall(); // Create a new region and install the core bundle into it. Region user = digraph.createRegion("user"); // Allow everything from the kernel region into the user region so the // core bundle will resolve. user.connectRegion( kernel, digraph.createRegionFilterBuilder().allowAll(RegionFilter.VISIBLE_ALL_NAMESPACE).build()); // Allow everything from the user region into the kernel region so the // root subsystem service can be found. kernel.connectRegion( user, digraph.createRegionFilterBuilder().allowAll(RegionFilter.VISIBLE_ALL_NAMESPACE).build()); core = user.installBundle(normalizeBundleLocation(core.getLocation())); user = digraph.getRegion(core); core.start(); root = getRootSubsystem(); region = digraph.getRegion(root.getBundleContext().getBundle()); // The root subsystem should now be in the new region. assertEquals("Wrong region", user, region); // Extra test. Install application A into the root region (user) and // make sure it resolves. Although the system bundle is in the kernel // region and not a constituent of the root subsystem, the capability // should still be found and used. try { Subsystem applicationA = installSubsystemFromFile(root, APPLICATION_A); uninstallSubsystemSilently(applicationA); } catch (Exception e) { e.printStackTrace(); fail("Subsystem should have installed"); } } }