| /******************************************************************************* |
| * Copyright (c) 2011, 2015 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.equinox.region.tests.system; |
| |
| import java.io.IOException; |
| import java.lang.management.ManagementFactory; |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| import java.util.*; |
| import java.util.concurrent.CopyOnWriteArrayList; |
| import javax.management.*; |
| import org.eclipse.equinox.region.*; |
| import org.osgi.framework.*; |
| import org.osgi.framework.hooks.bundle.CollisionHook; |
| import org.osgi.framework.hooks.bundle.EventHook; |
| import org.osgi.framework.hooks.resolver.ResolverHook; |
| import org.osgi.framework.hooks.resolver.ResolverHookFactory; |
| import org.osgi.framework.wiring.*; |
| import org.osgi.util.tracker.ServiceTracker; |
| |
| public class RegionSystemTests extends AbstractRegionSystemTest { |
| |
| private static final long TEST_BUNDLE_ID = 452345245L; |
| |
| public void testBasic() throws BundleException, InvalidSyntaxException, InterruptedException { |
| // get the system region |
| Region systemRegion = digraph.getRegion(0); |
| // create a disconnected test region |
| Region testRegion = digraph.createRegion(getName()); |
| List<Bundle> bundles = new ArrayList<Bundle>(); |
| // Install all test bundles |
| Bundle pp1, cp2, sc1; |
| bundles.add(pp1 = bundleInstaller.installBundle(PP1, testRegion)); |
| // should be able to start pp1 because it depends on nothing |
| pp1.start(); |
| // do a sanity check that we have no services available in the isolated region |
| assertNull("Found some services.", pp1.getBundleContext().getAllServiceReferences(null, null)); |
| assertEquals("Found extra bundles in region", 1, pp1.getBundleContext().getBundles().length); |
| pp1.stop(); |
| |
| bundles.add(bundleInstaller.installBundle(SP1, testRegion)); |
| bundles.add(bundleInstaller.installBundle(CP1, testRegion)); |
| bundles.add(bundleInstaller.installBundle(PP2, testRegion)); |
| bundles.add(bundleInstaller.installBundle(SP2, testRegion)); |
| bundles.add(cp2 = bundleInstaller.installBundle(CP2, testRegion)); |
| bundles.add(bundleInstaller.installBundle(PC1, testRegion)); |
| bundles.add(bundleInstaller.installBundle(BC1, testRegion)); |
| bundles.add(sc1 = bundleInstaller.installBundle(SC1, testRegion)); |
| bundles.add(bundleInstaller.installBundle(CC1, testRegion)); |
| |
| // Import the system bundle from the systemRegion |
| digraph.connect(testRegion, digraph.createRegionFilterBuilder().allow(RegionFilter.VISIBLE_BUNDLE_NAMESPACE, "(id=0)").build(), systemRegion); |
| // must import Boolean services into systemRegion to test |
| digraph.connect(systemRegion, digraph.createRegionFilterBuilder().allow(RegionFilter.VISIBLE_SERVICE_NAMESPACE, "(objectClass=java.lang.Boolean)").build(), testRegion); |
| |
| bundleInstaller.resolveBundles(bundles.toArray(new Bundle[bundles.size()])); |
| for (Bundle bundle : bundles) { |
| assertEquals("Bundle did not resolve: " + bundle.getSymbolicName(), Bundle.RESOLVED, bundle.getState()); |
| bundle.start(); |
| } |
| BundleContext context = getContext(); |
| ServiceTracker<Boolean, Boolean> cp2Tracker = new ServiceTracker<Boolean, Boolean>(context, context.createFilter("(&(objectClass=java.lang.Boolean)(bundle.id=" + cp2.getBundleId() + "))"), null); |
| ServiceTracker<Boolean, Boolean> sc1Tracker = new ServiceTracker<Boolean, Boolean>(context, context.createFilter("(&(objectClass=java.lang.Boolean)(bundle.id=" + sc1.getBundleId() + "))"), null); |
| |
| cp2Tracker.open(); |
| sc1Tracker.open(); |
| |
| assertNotNull("The cp2 bundle never found the service.", cp2Tracker.waitForService(2000)); |
| assertNotNull("The sc1 bundle never found the service.", sc1Tracker.waitForService(2000)); |
| cp2Tracker.close(); |
| sc1Tracker.close(); |
| } |
| |
| public void testSingleBundleRegions() throws BundleException, InvalidSyntaxException, InterruptedException { |
| // get the system region |
| Region systemRegion = digraph.getRegion(0); |
| Map<String, Bundle> bundles = new HashMap<String, Bundle>(); |
| // create a disconnected test region for each test bundle |
| for (String location : ALL) { |
| Region testRegion = digraph.createRegion(location); |
| bundles.put(location, bundleInstaller.installBundle(location, testRegion)); |
| // Import the system bundle from the systemRegion |
| digraph.connect(testRegion, digraph.createRegionFilterBuilder().allow(RegionFilter.VISIBLE_BUNDLE_NAMESPACE, "(id=0)").build(), systemRegion); |
| // must import Boolean services into systemRegion to test |
| digraph.connect(systemRegion, digraph.createRegionFilterBuilder().allow(RegionFilter.VISIBLE_SERVICE_NAMESPACE, "(objectClass=java.lang.Boolean)").build(), testRegion); |
| } |
| |
| bundleInstaller.resolveBundles(bundles.values().toArray(new Bundle[bundles.size()])); |
| assertEquals(PP1, Bundle.RESOLVED, bundles.get(PP1).getState()); |
| assertEquals(SP1, Bundle.INSTALLED, bundles.get(SP1).getState()); |
| assertEquals(CP1, Bundle.RESOLVED, bundles.get(CP1).getState()); |
| assertEquals(PP2, Bundle.INSTALLED, bundles.get(PP2).getState()); |
| assertEquals(SP2, Bundle.INSTALLED, bundles.get(SP2).getState()); |
| assertEquals(CP2, Bundle.INSTALLED, bundles.get(CP2).getState()); |
| assertEquals(BC1, Bundle.INSTALLED, bundles.get(BC1).getState()); |
| assertEquals(SC1, Bundle.INSTALLED, bundles.get(SC1).getState()); |
| assertEquals(CC1, Bundle.INSTALLED, bundles.get(CC1).getState()); |
| |
| // now make the necessary connections |
| // SP1 |
| digraph.connect(digraph.getRegion(SP1), digraph.createRegionFilterBuilder().allow(RegionFilter.VISIBLE_PACKAGE_NAMESPACE, "(" + RegionFilter.VISIBLE_PACKAGE_NAMESPACE + "=pkg1.*)").build(), digraph.getRegion(PP1)); |
| // PP2 |
| digraph.connect(digraph.getRegion(PP2), digraph.createRegionFilterBuilder().allow(CP1, "(name=" + CP1 + ")").build(), digraph.getRegion(CP1)); |
| // SP2 |
| digraph.connect(digraph.getRegion(SP2), digraph.createRegionFilterBuilder().allow(RegionFilter.VISIBLE_PACKAGE_NAMESPACE, "(" + RegionFilter.VISIBLE_PACKAGE_NAMESPACE + "=pkg2.*)").build(), digraph.getRegion(PP2)); |
| // CP2 |
| digraph.connect(digraph.getRegion(CP2), digraph.createRegionFilterBuilder().allow(RegionFilter.VISIBLE_PACKAGE_NAMESPACE, "(" + RegionFilter.VISIBLE_PACKAGE_NAMESPACE + "=pkg1.*)").build(), digraph.getRegion(PP1)); |
| digraph.connect(digraph.getRegion(CP2), digraph.createRegionFilterBuilder().allow(RegionFilter.VISIBLE_SERVICE_NAMESPACE, "(" + Constants.OBJECTCLASS + "=pkg1.*)").build(), digraph.getRegion(SP1)); |
| // PC1 |
| digraph.connect(digraph.getRegion(PC1), digraph.createRegionFilterBuilder().allow(RegionFilter.VISIBLE_PACKAGE_NAMESPACE, "(" + RegionFilter.VISIBLE_PACKAGE_NAMESPACE + "=pkg2.*)").build(), digraph.getRegion(PP2)); |
| // BC1 |
| digraph.connect(digraph.getRegion(BC1), digraph.createRegionFilterBuilder().allow(RegionFilter.VISIBLE_REQUIRE_NAMESPACE, "(" + RegionFilter.VISIBLE_REQUIRE_NAMESPACE + "=" + PP2 + ")").build(), digraph.getRegion(PP2)); |
| // SC1 |
| digraph.connect(digraph.getRegion(SC1), digraph.createRegionFilterBuilder().allow(RegionFilter.VISIBLE_PACKAGE_NAMESPACE, "(" + RegionFilter.VISIBLE_PACKAGE_NAMESPACE + "=pkg2.*)").build(), digraph.getRegion(PP2)); |
| digraph.connect(digraph.getRegion(SC1), digraph.createRegionFilterBuilder().allow(RegionFilter.VISIBLE_SERVICE_NAMESPACE, "(" + Constants.OBJECTCLASS + "=pkg2.*)").build(), digraph.getRegion(SP2)); |
| // CC1 |
| digraph.connect(digraph.getRegion(CC1), digraph.createRegionFilterBuilder().allow(CP2, "(name=" + CP2 + ")").build(), digraph.getRegion(CP2)); |
| |
| bundleInstaller.resolveBundles(bundles.values().toArray(new Bundle[bundles.size()])); |
| for (Bundle bundle : bundles.values()) { |
| assertEquals("Bundle did not resolve: " + bundle.getSymbolicName(), Bundle.RESOLVED, bundle.getState()); |
| bundle.start(); |
| } |
| BundleContext context = getContext(); |
| ServiceTracker<Boolean, Boolean> cp2Tracker = new ServiceTracker<Boolean, Boolean>(context, context.createFilter("(&(objectClass=java.lang.Boolean)(bundle.id=" + bundles.get(CP2).getBundleId() + "))"), null); |
| ServiceTracker<Boolean, Boolean> sc1Tracker = new ServiceTracker<Boolean, Boolean>(context, context.createFilter("(&(objectClass=java.lang.Boolean)(bundle.id=" + bundles.get(SC1).getBundleId() + "))"), null); |
| |
| cp2Tracker.open(); |
| sc1Tracker.open(); |
| |
| assertNotNull("The cp2 bundle never found the service.", cp2Tracker.waitForService(2000)); |
| assertNotNull("The sc1 bundle never found the service.", sc1Tracker.waitForService(2000)); |
| cp2Tracker.close(); |
| sc1Tracker.close(); |
| } |
| |
| // public void testPersistence() throws BundleException, InvalidSyntaxException { |
| // // get the system region |
| // Region systemRegion = digraph.getRegion(0); |
| // Map<String, Bundle> bundles = new HashMap<String, Bundle>(); |
| // // create a disconnected test region for each test bundle |
| // for (String location : ALL) { |
| // Region testRegion = digraph.createRegion(location); |
| // bundles.put(location, bundleInstaller.installBundle(location, testRegion)); |
| // // Import the system bundle from the systemRegion |
| // digraph.connect(testRegion, digraph.createRegionFilterBuilder().allow(RegionFilter.VISIBLE_BUNDLE_NAMESPACE, "(id=0)").build(), systemRegion); |
| // // must import Boolean services into systemRegion to test |
| // digraph.connect(systemRegion, digraph.createRegionFilterBuilder().allow(RegionFilter.VISIBLE_SERVICE_NAMESPACE, "(objectClass=java.lang.Boolean)").build(), testRegion); |
| // } |
| // |
| // bundleInstaller.resolveBundles(bundles.values().toArray(new Bundle[bundles.size()])); |
| // assertEquals(PP1, Bundle.RESOLVED, bundles.get(PP1).getState()); |
| // assertEquals(SP1, Bundle.INSTALLED, bundles.get(SP1).getState()); |
| // assertEquals(CP1, Bundle.RESOLVED, bundles.get(CP1).getState()); |
| // assertEquals(PP2, Bundle.INSTALLED, bundles.get(PP2).getState()); |
| // assertEquals(SP2, Bundle.INSTALLED, bundles.get(SP2).getState()); |
| // assertEquals(CP2, Bundle.INSTALLED, bundles.get(CP2).getState()); |
| // assertEquals(BC1, Bundle.INSTALLED, bundles.get(BC1).getState()); |
| // assertEquals(SC1, Bundle.INSTALLED, bundles.get(SC1).getState()); |
| // assertEquals(CC1, Bundle.INSTALLED, bundles.get(CC1).getState()); |
| // |
| // regionBundle.stop(); |
| // bundleInstaller.resolveBundles(bundles.values().toArray(new Bundle[bundles.size()])); |
| // assertEquals(PP1, Bundle.RESOLVED, bundles.get(PP1).getState()); |
| // assertEquals(SP1, Bundle.RESOLVED, bundles.get(SP1).getState()); |
| // assertEquals(CP1, Bundle.RESOLVED, bundles.get(CP1).getState()); |
| // assertEquals(PP2, Bundle.RESOLVED, bundles.get(PP2).getState()); |
| // assertEquals(SP2, Bundle.RESOLVED, bundles.get(SP2).getState()); |
| // assertEquals(CP2, Bundle.RESOLVED, bundles.get(CP2).getState()); |
| // assertEquals(BC1, Bundle.RESOLVED, bundles.get(BC1).getState()); |
| // assertEquals(SC1, Bundle.RESOLVED, bundles.get(SC1).getState()); |
| // assertEquals(CC1, Bundle.RESOLVED, bundles.get(CC1).getState()); |
| // |
| // startRegionBundle(); |
| // |
| // bundleInstaller.refreshPackages(bundles.values().toArray(new Bundle[bundles.size()])); |
| // assertEquals(PP1, Bundle.RESOLVED, bundles.get(PP1).getState()); |
| // assertEquals(SP1, Bundle.INSTALLED, bundles.get(SP1).getState()); |
| // assertEquals(CP1, Bundle.RESOLVED, bundles.get(CP1).getState()); |
| // assertEquals(PP2, Bundle.INSTALLED, bundles.get(PP2).getState()); |
| // assertEquals(SP2, Bundle.INSTALLED, bundles.get(SP2).getState()); |
| // assertEquals(CP2, Bundle.INSTALLED, bundles.get(CP2).getState()); |
| // assertEquals(BC1, Bundle.INSTALLED, bundles.get(BC1).getState()); |
| // assertEquals(SC1, Bundle.INSTALLED, bundles.get(SC1).getState()); |
| // assertEquals(CC1, Bundle.INSTALLED, bundles.get(CC1).getState()); |
| // } |
| // |
| // public void testPersistenceBug343020() throws BundleException, InvalidSyntaxException { |
| // // get the system region |
| // Region systemRegion = digraph.getRegion(0); |
| // // create a test region |
| // Region testRegion = digraph.createRegion(getName()); |
| // |
| // RegionFilterBuilder builder = digraph.createRegionFilterBuilder(); |
| // // Import the system bundle from the systemRegion |
| // builder.allow(RegionFilter.VISIBLE_BUNDLE_NAMESPACE, "(id=0)"); |
| // // import PP1 |
| // builder.allow(RegionFilter.VISIBLE_PACKAGE_NAMESPACE, "(" + RegionFilter.VISIBLE_PACKAGE_NAMESPACE + "=pkg1.*)"); |
| // digraph.connect(testRegion, builder.build(), systemRegion); |
| // // install CP2 |
| // Bundle cp2 = bundleInstaller.installBundle(CP2, testRegion); |
| // |
| // bundleInstaller.resolveBundles(new Bundle[] {cp2}); |
| // assertEquals("Wrong state for pc1.", Bundle.INSTALLED, cp2.getState()); |
| // |
| // regionBundle.stop(); |
| // |
| // // install PP1 there is no region alive |
| // bundleInstaller.installBundle(PP1); |
| // |
| // // start region bundle and confirm we can resolve cp2 now |
| // startRegionBundle(); |
| // |
| // bundleInstaller.refreshPackages(new Bundle[] {cp2}); |
| // assertEquals("Wrong state for pc1.", Bundle.RESOLVED, cp2.getState()); |
| // |
| // // stop region bundle to test uninstalling bundles while stopped |
| // regionBundle.stop(); |
| // cp2.uninstall(); |
| // |
| // startRegionBundle(); |
| // testRegion = digraph.getRegion(getName()); |
| // assertNotNull("No test region found.", testRegion); |
| // Set<Long> testIds = testRegion.getBundleIds(); |
| // assertEquals("Wrong number of test ids.", 0, testIds.size()); |
| // } |
| |
| public void testCyclicRegions0() throws BundleException, InvalidSyntaxException, InterruptedException { |
| doCyclicRegions(0); |
| } |
| |
| public void testCyclicRegions10() throws BundleException, InvalidSyntaxException, InterruptedException { |
| doCyclicRegions(10); |
| } |
| |
| public void testCyclicRegions100() throws BundleException, InvalidSyntaxException, InterruptedException { |
| doCyclicRegions(100); |
| } |
| |
| private void doCyclicRegions(int numLevels) throws BundleException, InvalidSyntaxException, InterruptedException { |
| String regionName1 = getName() + "_1"; |
| String regionName2 = getName() + "_2"; |
| // get the system region |
| Region systemRegion = digraph.getRegion(0); |
| // create two regions to hold the bundles |
| Region testRegion1 = digraph.createRegion(regionName1); |
| Region testRegion2 = digraph.createRegion(regionName2); |
| // connect to the system bundle |
| testRegion1.connectRegion(systemRegion, digraph.createRegionFilterBuilder().allow(RegionFilter.VISIBLE_BUNDLE_NAMESPACE, "(id=0)").build()); |
| testRegion2.connectRegion(systemRegion, digraph.createRegionFilterBuilder().allow(RegionFilter.VISIBLE_BUNDLE_NAMESPACE, "(id=0)").build()); |
| // must import Boolean services into systemRegion to test |
| systemRegion.connectRegion(testRegion1, digraph.createRegionFilterBuilder().allow(RegionFilter.VISIBLE_SERVICE_NAMESPACE, "(objectClass=java.lang.Boolean)").build()); |
| systemRegion.connectRegion(testRegion2, digraph.createRegionFilterBuilder().allow(RegionFilter.VISIBLE_SERVICE_NAMESPACE, "(objectClass=java.lang.Boolean)").build()); |
| |
| Map<String, Bundle> bundles = new HashMap<String, Bundle>(); |
| // add bundles to region1 |
| bundles.put(PP1, bundleInstaller.installBundle(PP1, testRegion1)); |
| bundles.put(SP2, bundleInstaller.installBundle(SP2, testRegion1)); |
| bundles.put(CP2, bundleInstaller.installBundle(CP2, testRegion1)); |
| bundles.put(PC1, bundleInstaller.installBundle(PC1, testRegion1)); |
| bundles.put(BC1, bundleInstaller.installBundle(BC1, testRegion1)); |
| |
| // add bundles to region2 |
| bundles.put(SP1, bundleInstaller.installBundle(SP1, testRegion2)); |
| bundles.put(CP1, bundleInstaller.installBundle(CP1, testRegion2)); |
| bundles.put(PP2, bundleInstaller.installBundle(PP2, testRegion2)); |
| bundles.put(SC1, bundleInstaller.installBundle(SC1, testRegion2)); |
| bundles.put(CC1, bundleInstaller.installBundle(CC1, testRegion2)); |
| |
| RegionFilterBuilder testRegionFilter1 = digraph.createRegionFilterBuilder(); |
| // SP2 -> PP2 |
| testRegionFilter1.allow(RegionFilter.VISIBLE_PACKAGE_NAMESPACE, "(" + RegionFilter.VISIBLE_PACKAGE_NAMESPACE + "=pkg2.*)"); |
| // CP2 -> SP1 |
| testRegionFilter1.allow(RegionFilter.VISIBLE_SERVICE_NAMESPACE, "(" + Constants.OBJECTCLASS + "=pkg1.*)"); |
| // PC1 -> PP2 |
| // this is not needed because we already import pkg2.* above |
| //testRegionFilter1.allow(RegionFilter.VISIBLE_PACKAGE_NAMESPACE, "(" + RegionFilter.VISIBLE_PACKAGE_NAMESPACE + "=pkg2.*)"); |
| // BC1 -> PP2 |
| testRegionFilter1.allow(RegionFilter.VISIBLE_REQUIRE_NAMESPACE, "(" + RegionFilter.VISIBLE_REQUIRE_NAMESPACE + "=" + PP2 + ")"); |
| |
| RegionFilterBuilder testRegionFilter2 = digraph.createRegionFilterBuilder(); |
| //SP1 -> PP1 |
| testRegionFilter2.allow(RegionFilter.VISIBLE_PACKAGE_NAMESPACE, "(" + RegionFilter.VISIBLE_PACKAGE_NAMESPACE + "=pkg1.*)"); |
| //SC1 -> SP2 |
| testRegionFilter2.allow(RegionFilter.VISIBLE_SERVICE_NAMESPACE, "(" + Constants.OBJECTCLASS + "=pkg2.*)"); |
| //CC1 -> CP2 |
| testRegionFilter2.allow(CP2, "(name=" + CP2 + ")"); |
| |
| Region r1, r2 = null; |
| for (int i = 0; i <= numLevels; i++) { |
| r1 = (i > 0) ? r2 : testRegion1; |
| r2 = (i < numLevels) ? digraph.createRegion(getName() + "_level_" + i) : testRegion2; |
| r1.connectRegion(r2, testRegionFilter1.build()); |
| r2.connectRegion(r1, testRegionFilter2.build()); |
| } |
| |
| bundleInstaller.resolveBundles(bundles.values().toArray(new Bundle[bundles.size()])); |
| for (Bundle bundle : bundles.values()) { |
| assertEquals("Bundle did not resolve: " + bundle.getSymbolicName(), Bundle.RESOLVED, bundle.getState()); |
| bundle.start(); |
| } |
| BundleContext context = getContext(); |
| ServiceTracker<Boolean, Boolean> cp2Tracker = new ServiceTracker<Boolean, Boolean>(context, context.createFilter("(&(objectClass=java.lang.Boolean)(bundle.id=" + bundles.get(CP2).getBundleId() + "))"), null); |
| ServiceTracker<Boolean, Boolean> sc1Tracker = new ServiceTracker<Boolean, Boolean>(context, context.createFilter("(&(objectClass=java.lang.Boolean)(bundle.id=" + bundles.get(SC1).getBundleId() + "))"), null); |
| |
| cp2Tracker.open(); |
| sc1Tracker.open(); |
| |
| assertNotNull("The cp2 bundle never found the service.", cp2Tracker.waitForService(2000)); |
| assertNotNull("The sc1 bundle never found the service.", sc1Tracker.waitForService(2000)); |
| cp2Tracker.close(); |
| sc1Tracker.close(); |
| } |
| |
| private ServiceRegistration<ResolverHookFactory> disableAllResolves() { |
| return getContext().registerService(ResolverHookFactory.class, new ResolverHookFactory() { |
| |
| @Override |
| public ResolverHook begin(Collection<BundleRevision> triggers) { |
| return new ResolverHook() { |
| |
| @Override |
| public void filterSingletonCollisions(BundleCapability singleton, Collection<BundleCapability> collisionCandidates) { |
| // nothing; |
| } |
| |
| @Override |
| public void filterResolvable(Collection<BundleRevision> candidates) { |
| // prevent all resolves |
| candidates.clear(); |
| } |
| |
| @Override |
| public void filterMatches(BundleRequirement requirement, Collection<BundleCapability> candidates) { |
| // nothing; |
| } |
| |
| @Override |
| public void end() { |
| // TODO Auto-generated method stub |
| |
| } |
| }; |
| } |
| }, null); |
| } |
| |
| public void testSingletons() throws BundleException { |
| Region region1 = digraph.createRegion(getName() + "_1"); |
| Region region2 = digraph.createRegion(getName() + "_2"); |
| |
| // first install into the same region; higher version 2 should resolve |
| Bundle singleton1 = bundleInstaller.installBundle(SINGLETON1, region1); |
| Bundle singleton2 = bundleInstaller.installBundle(SINGLETON2, region1); |
| assertFalse(bundleInstaller.resolveBundles(new Bundle[] {singleton1, singleton2})); |
| assertEquals("singleton1", Bundle.INSTALLED, singleton1.getState()); |
| assertEquals("singleton2", Bundle.RESOLVED, singleton2.getState()); |
| |
| // now install into different regions; both 1 and 2 should resolve |
| singleton2.uninstall(); |
| singleton2 = bundleInstaller.installBundle(SINGLETON2, region2); |
| assertTrue(bundleInstaller.resolveBundles(new Bundle[] {singleton1, singleton2})); |
| assertEquals("singleton1", Bundle.RESOLVED, singleton1.getState()); |
| assertEquals("singleton2", Bundle.RESOLVED, singleton2.getState()); |
| |
| ServiceRegistration<ResolverHookFactory> disableHook = disableAllResolves(); |
| try { |
| // now refresh to get us to an unresolved state again |
| bundleInstaller.refreshPackages(new Bundle[] {singleton1, singleton2}); |
| // connect region2 -> region1 |
| region2.connectRegion(region1, digraph.createRegionFilterBuilder().allowAll(RegionFilter.VISIBLE_BUNDLE_NAMESPACE).build()); |
| // enable resolving again |
| disableHook.unregister(); |
| disableHook = null; |
| |
| assertFalse(bundleInstaller.resolveBundles(new Bundle[] {singleton1, singleton2})); |
| assertTrue("One and only singleton bundle should be resolved", (singleton1.getState() == Bundle.RESOLVED) ^ (singleton2.getState() == Bundle.RESOLVED)); |
| |
| singleton2.uninstall(); |
| disableHook = disableAllResolves(); |
| // now refresh to get us to an unresolved state again |
| bundleInstaller.refreshPackages(new Bundle[] {singleton1, singleton2}); |
| // enable resolving again |
| disableHook.unregister(); |
| disableHook = null; |
| |
| // make sure singleton1 is resolved first |
| assertTrue(bundleInstaller.resolveBundles(new Bundle[] {singleton1})); |
| assertEquals("singleton1", Bundle.RESOLVED, singleton1.getState()); |
| singleton2 = bundleInstaller.installBundle(SINGLETON2, region2); |
| assertFalse(bundleInstaller.resolveBundles(new Bundle[] {singleton2})); |
| assertEquals("singleton2", Bundle.INSTALLED, singleton2.getState()); |
| |
| singleton1.uninstall(); |
| disableHook = disableAllResolves(); |
| // now refresh to get us to an unresolved state again |
| bundleInstaller.refreshPackages(new Bundle[] {singleton1, singleton2}); |
| // enable resolving again |
| disableHook.unregister(); |
| disableHook = null; |
| |
| // make sure singleton2 is resolved first |
| assertTrue(bundleInstaller.resolveBundles(new Bundle[] {singleton2})); |
| assertEquals("singleton2", Bundle.RESOLVED, singleton2.getState()); |
| singleton1 = bundleInstaller.installBundle(SINGLETON1, region1); |
| assertFalse(bundleInstaller.resolveBundles(new Bundle[] {singleton1})); |
| assertEquals("singleton1", Bundle.INSTALLED, singleton1.getState()); |
| } finally { |
| if (disableHook != null) |
| disableHook.unregister(); |
| } |
| } |
| |
| private static final String REGION_DOMAIN_PROP = "org.eclipse.equinox.region.domain"; |
| |
| public void testMbeans() throws MalformedObjectNameException, BundleException, InstanceNotFoundException, ReflectionException, MBeanException, AttributeNotFoundException { |
| MBeanServer server = ManagementFactory.getPlatformMBeanServer(); |
| ObjectName digraphName = new ObjectName(REGION_DOMAIN_PROP + ":type=RegionDigraph,*"); |
| ObjectName regionNameAllQuery = new ObjectName(REGION_DOMAIN_PROP + ":type=Region,name=*,*"); |
| Set<ObjectInstance> digraphs = server.queryMBeans(null, digraphName); |
| assertEquals("Expected only one instance of digraph", 1, digraphs.size()); |
| Set<ObjectInstance> regions = server.queryMBeans(null, regionNameAllQuery); |
| assertEquals("Expected only one instance of region", 1, regions.size()); |
| |
| Region pp1Region = digraph.createRegion(PP1); |
| Bundle pp1Bundle = bundleInstaller.installBundle(PP1, pp1Region); |
| Region sp1Region = digraph.createRegion(SP1); |
| Bundle sp1Bundle = bundleInstaller.installBundle(SP1, sp1Region); |
| |
| regions = server.queryMBeans(null, regionNameAllQuery); |
| assertEquals("Wrong number of regions", 3, regions.size()); |
| |
| Set<ObjectInstance> pp1Query = server.queryMBeans(null, new ObjectName(REGION_DOMAIN_PROP + ":type=Region,name=" + PP1 + ",*")); |
| assertEquals("Expected only one instance of: " + PP1, 1, pp1Query.size()); |
| Set<ObjectInstance> sp1Query = server.queryMBeans(null, new ObjectName(REGION_DOMAIN_PROP + ":type=Region,name=" + SP1 + ",*")); |
| assertEquals("Expected only one instance of: " + SP1, 1, sp1Query.size()); |
| ObjectName pp1Name = (ObjectName) server.invoke(digraphs.iterator().next().getObjectName(), "getRegion", new Object[] {PP1}, new String[] {String.class.getName()}); |
| assertEquals(PP1 + " regions not equal.", pp1Query.iterator().next().getObjectName(), pp1Name); |
| ObjectName sp1Name = (ObjectName) server.invoke(digraphs.iterator().next().getObjectName(), "getRegion", new Object[] {SP1}, new String[] {String.class.getName()}); |
| assertEquals(SP1 + " regions not equal.", sp1Query.iterator().next().getObjectName(), sp1Name); |
| |
| // test non existing region |
| ObjectName shouldNotExistName = (ObjectName) server.invoke(digraphs.iterator().next().getObjectName(), "getRegion", new Object[] {"ShouldNotExist"}, new String[] {String.class.getName()}); |
| assertNull("Should not exist", shouldNotExistName); |
| |
| long[] bundleIds = (long[]) server.getAttribute(pp1Name, "BundleIds"); |
| assertEquals("Wrong number of bundles", 1, bundleIds.length); |
| assertEquals("Wrong bundle", pp1Bundle.getBundleId(), bundleIds[0]); |
| String name = (String) server.getAttribute(pp1Name, "Name"); |
| assertEquals("Wrong name", PP1, name); |
| |
| bundleIds = (long[]) server.getAttribute(sp1Name, "BundleIds"); |
| assertEquals("Wrong number of bundles", 1, bundleIds.length); |
| assertEquals("Wrong bundle", sp1Bundle.getBundleId(), bundleIds[0]); |
| name = (String) server.getAttribute(sp1Name, "Name"); |
| assertEquals("Wrong name", SP1, name); |
| } |
| |
| public void testBundleCollisionDisconnectedRegions() throws BundleException, InvalidSyntaxException { |
| // get the system region |
| Region systemRegion = digraph.getRegion(0); |
| Collection<Bundle> bundles = new HashSet<Bundle>(); |
| // create 4 disconnected test regions and install each bundle into each region |
| int numRegions = 4; |
| String regionName = "IsolatedRegion_"; |
| for (int i = 0; i < numRegions; i++) { |
| Region region = digraph.createRegion(regionName + i); |
| // Import the system bundle from the systemRegion |
| digraph.connect(region, digraph.createRegionFilterBuilder().allow(RegionFilter.VISIBLE_BUNDLE_NAMESPACE, "(id=0)").build(), systemRegion); |
| // must import Boolean services into systemRegion to test |
| digraph.connect(systemRegion, digraph.createRegionFilterBuilder().allow(RegionFilter.VISIBLE_SERVICE_NAMESPACE, "(objectClass=java.lang.Boolean)").build(), region); |
| for (String location : ALL) { |
| Bundle b = bundleInstaller.installBundle(location, region); |
| bundles.add(b); |
| } |
| } |
| |
| assertEquals("Wrong number of bundles installed", numRegions * ALL.size(), bundles.size()); |
| assertTrue("Could not resolve bundles.", bundleInstaller.resolveBundles(bundles.toArray(new Bundle[bundles.size()]))); |
| |
| // test install of duplicates |
| for (int i = 0; i < numRegions; i++) { |
| Region region = digraph.getRegion(regionName + i); |
| for (String name : ALL) { |
| String location = bundleInstaller.getBundleLocation(name); |
| try { |
| Bundle b = region.installBundle(getName() + "_expectToFail", new URL(location).openStream()); |
| b.uninstall(); |
| fail("Expected a bundle exception on duplicate bundle installation: " + name); |
| } catch (BundleException e) { |
| // expected |
| assertEquals("Wrong exception type.", BundleException.DUPLICATE_BUNDLE_ERROR, e.getType()); |
| } catch (IOException e) { |
| fail("Failed to open bunldle location: " + e.getMessage()); |
| } |
| } |
| } |
| |
| // test update to a duplicate |
| for (int i = 0; i < numRegions; i++) { |
| Region region = digraph.getRegion(regionName + i); |
| |
| Bundle regionPP1 = region.getBundle(PP1, new Version(1, 0, 0)); |
| |
| String locationSP1 = bundleInstaller.getBundleLocation(SP1); |
| try { |
| regionPP1.update(new URL(locationSP1).openStream()); |
| fail("Expected a bundle exception on duplicate bundle update: " + region); |
| } catch (BundleException e) { |
| // expected |
| assertEquals("Wrong exception type.", BundleException.DUPLICATE_BUNDLE_ERROR, e.getType()); |
| } catch (IOException e) { |
| fail("Failed to open bunldle location: " + e.getMessage()); |
| } |
| |
| // now uninstall SP1 and try to update PP1 to SP1 again |
| Bundle regionSP1 = region.getBundle(SP1, new Version(1, 0, 0)); |
| regionSP1.uninstall(); |
| |
| try { |
| regionPP1.update(new URL(locationSP1).openStream()); |
| } catch (IOException e) { |
| fail("Failed to open bunldle location: " + e.getMessage()); |
| } |
| } |
| } |
| |
| public void testBundleCollisionUninstalledBundle() throws BundleException { |
| Region region1 = digraph.createRegion(getName() + 1); |
| Region region2 = digraph.createRegion(getName() + 2); |
| Region region3 = digraph.createRegion(getName() + 3); |
| // install the same bundle into the first two regions. Should be no collision |
| bundleInstaller.installBundle(PP1, region1); |
| bundleInstaller.installBundle(PP1, region2); |
| |
| ServiceRegistration<CollisionHook> collisionHookREg = getContext().registerService(CollisionHook.class, new CollisionHook() { |
| @Override |
| public void filterCollisions(int operationType, Bundle target, Collection<Bundle> collisionCandidates) { |
| for (Bundle bundle : collisionCandidates) { |
| try { |
| bundle.uninstall(); |
| } catch (BundleException e) { |
| e.printStackTrace(); |
| } |
| } |
| } |
| }, new Hashtable<String, Object>(Collections.singletonMap(Constants.SERVICE_RANKING, Integer.MAX_VALUE))); |
| try { |
| bundleInstaller.installBundle(PP1, region3); |
| } finally { |
| collisionHookREg.unregister(); |
| } |
| } |
| |
| public void testBundleCollisionConnectedRegions() throws BundleException, InvalidSyntaxException { |
| // get the system region |
| Region systemRegion = digraph.getRegion(0); |
| // create 3 connected test regions and install each bundle into each region |
| int numRegions = 4; |
| String regionName = "ConnectedRegion_"; |
| for (int i = 0; i < numRegions; i++) { |
| Region region = digraph.createRegion(regionName + i); |
| // Import the system bundle from the systemRegion |
| digraph.connect(region, digraph.createRegionFilterBuilder().allow(RegionFilter.VISIBLE_BUNDLE_NAMESPACE, "(id=0)").build(), systemRegion); |
| // must import Boolean services into systemRegion to test |
| digraph.connect(systemRegion, digraph.createRegionFilterBuilder().allow(RegionFilter.VISIBLE_SERVICE_NAMESPACE, "(objectClass=java.lang.Boolean)").build(), region); |
| } |
| |
| Region region0 = digraph.getRegion(regionName + 0); |
| Region region1 = digraph.getRegion(regionName + 1); |
| Region region2 = digraph.getRegion(regionName + 2); |
| |
| // create connections that share the bundles we want |
| RegionFilterBuilder filterBuilder = digraph.createRegionFilterBuilder(); |
| filterBuilder.allow(RegionFilter.VISIBLE_BUNDLE_NAMESPACE, "(bundle-symbolic-name=" + PP1 + ")"); |
| filterBuilder.allow(RegionFilter.VISIBLE_BUNDLE_NAMESPACE, "(bundle-symbolic-name=" + SP1 + ")"); |
| filterBuilder.allow(RegionFilter.VISIBLE_BUNDLE_NAMESPACE, "(bundle-symbolic-name=" + CP1 + ")"); |
| region1.connectRegion(region0, filterBuilder.build()); |
| region2.connectRegion(region1, filterBuilder.build()); |
| |
| // install a bundle in each region |
| bundleInstaller.installBundle(PP1, region0); |
| bundleInstaller.installBundle(SP1, region1); |
| bundleInstaller.installBundle(CP1, region2); |
| |
| // Should not be able to install SP1 into region0 because that would collide with SP1->region1->region0 |
| assertInstallFail(SP1, region0); |
| // Should not be able to install PP1 into region1 because that would collide with region1->region0->PP1 |
| assertInstallFail(PP1, region1); |
| // Should not be able to install PP1 into region2 because that would collide with region2->region1->region0->PP1 |
| assertInstallFail(PP1, region2); |
| // Should not be able to install CP1 into region0 because that would collide with CP1->region2->region1->region0 |
| assertInstallFail(CP1, region0); |
| } |
| |
| private void assertInstallFail(String name, Region region) { |
| try { |
| Bundle b = bundleInstaller.installBundle(name, region); |
| b.uninstall(); |
| fail("Expected a bundle exception on duplicate bundle install: " + region); |
| } catch (BundleException e) { |
| // expected |
| assertEquals("Wrong exception type.", BundleException.DUPLICATE_BUNDLE_ERROR, e.getType()); |
| } |
| } |
| |
| public void testDefaultRegion() throws BundleException { |
| digraph.setDefaultRegion(null); |
| |
| Region systemRegion = digraph.getRegion(0); |
| Region pp1Region = digraph.createRegion(PP1); |
| |
| Bundle pp1Bundle = bundleInstaller.installBundle(PP1, null); |
| Region result = digraph.getRegion(pp1Bundle); |
| assertEquals("Wrong region", systemRegion, result); |
| |
| pp1Bundle.uninstall(); |
| |
| digraph.setDefaultRegion(pp1Region); |
| pp1Bundle = bundleInstaller.installBundle(PP1, null); |
| result = digraph.getRegion(pp1Bundle); |
| assertEquals("Wrong region", pp1Region, result); |
| |
| digraph.setDefaultRegion(null); |
| } |
| |
| public void testRemoveDefaultRegion() throws BundleException { |
| digraph.setDefaultRegion(null); |
| |
| Region pp1Region = digraph.createRegion(PP1); |
| digraph.setDefaultRegion(pp1Region); |
| digraph.removeRegion(pp1Region); |
| assertEquals("DefaultRegion is not null", null, digraph.getDefaultRegion()); |
| } |
| |
| public void testSetNotExistingDefaultRegion() throws BundleException { |
| Region pp1Region = digraph.createRegion(PP1); |
| digraph.removeRegion(pp1Region); |
| try { |
| digraph.setDefaultRegion(pp1Region); |
| assertFalse("IllegalArgumentException not thrown for setting non-existing region as default", true); |
| } catch (IllegalStateException _) { |
| assertNull("DefaultRegion is not null", digraph.getDefaultRegion()); |
| } |
| } |
| |
| public void testRemoveRegion() throws BundleException { |
| Region pp1Region = digraph.createRegion(PP1); |
| pp1Region.addBundle(TEST_BUNDLE_ID); |
| assertEquals("Region not associated with bundle id", pp1Region, digraph.getRegion(TEST_BUNDLE_ID)); |
| digraph.removeRegion(pp1Region); |
| assertNull("Region still associated with bundle id", digraph.getRegion(TEST_BUNDLE_ID)); |
| |
| // Adding a bundle to a removed region should not change the digraph and should error |
| try { |
| pp1Region.addBundle(TEST_BUNDLE_ID); |
| fail("Added a bundle to a region which was not part of a digraph"); |
| } catch (IllegalStateException e) { |
| // expected |
| } |
| assertNull("Region now associated with bundle id", digraph.getRegion(TEST_BUNDLE_ID)); |
| |
| Region pp2Region = digraph.createRegion(PP2); |
| pp2Region.addBundle(TEST_BUNDLE_ID); |
| |
| // removing a bundle from a removed region should not change the digraph and should error |
| try { |
| pp1Region.removeBundle(TEST_BUNDLE_ID); |
| fail("Removed a bundle via a region which was not part of a digraph"); |
| } catch (IllegalStateException e) { |
| // Expected |
| } |
| assertEquals("Wrong region found for the bundle id", pp2Region, digraph.getRegion(TEST_BUNDLE_ID)); |
| } |
| |
| public void testInstallAtLocation() throws BundleException, MalformedURLException, IOException { |
| // create disconnected test regions |
| Region r1 = digraph.createRegion(getName() + ".1"); |
| Region r2 = digraph.createRegion(getName() + ".2"); |
| |
| String location = bundleInstaller.getBundleLocation(PP1); |
| Bundle b1 = null; |
| Bundle b2 = null; |
| String l1 = null; |
| String l2 = null; |
| try { |
| URL url = new URL(location); |
| b1 = r1.installBundle(location + ".1", url.openStream()); |
| l1 = b1.getLocation(); |
| b2 = r2.installBundleAtLocation(location + ".2", url.openStream()); |
| l2 = b2.getLocation(); |
| } finally { |
| if (b1 != null) { |
| try { |
| b1.uninstall(); |
| } catch (BundleException e) { |
| // ignore |
| } |
| } |
| if (b2 != null) { |
| try { |
| b2.uninstall(); |
| } catch (BundleException e) { |
| // ignore |
| } |
| } |
| } |
| assertEquals("Wrong location found.", location + ".1#" + r1.getName(), l1); |
| assertEquals("Wrong location found.", location + ".2", l2); |
| } |
| |
| public void testInvalidRegionName() { |
| Collection<String> invalidNames = new ArrayList<String>(); |
| invalidNames.addAll(Arrays.asList(":", "bad:Name", ":bad::name:", ":badname", "badname:")); |
| invalidNames.addAll(Arrays.asList("=", "bad=Name", "=bad==name=", "=badname", "badname=")); |
| invalidNames.addAll(Arrays.asList("\n", "bad\nName", "\nbad\n\nname\n", "\nbadname", "badname\n")); |
| invalidNames.addAll(Arrays.asList("*", "bad*Name", "*bad**name*", "*badname", "badname*")); |
| invalidNames.addAll(Arrays.asList("?", "bad?Name", "?bad??name?", "?badname", "badname?")); |
| invalidNames.addAll(Arrays.asList(",", "bad,Name", ",bad,,name,", ",badname", "badname,")); |
| invalidNames.addAll(Arrays.asList("\"", "bad\"Name", "\"bad\"\"name\"", "\"badname", "badname\"")); |
| invalidNames.addAll(Arrays.asList("\\", "bad\\Name", "\\bad\\\\name\\", "\\badname", "badname\\")); |
| |
| for (String invalidName : invalidNames) { |
| try { |
| digraph.createRegion(invalidName); |
| fail("Expected failure to create region."); |
| } catch (IllegalArgumentException e) { |
| // expected |
| } catch (BundleException e) { |
| fail("Unexpected bundle exception: " + e.getMessage()); |
| } |
| } |
| |
| } |
| |
| public void testHigherRankedEventHook() throws BundleException { |
| final List<BundleEvent> events = new CopyOnWriteArrayList<BundleEvent>(); |
| SynchronousBundleListener listener = new SynchronousBundleListener() { |
| @Override |
| public void bundleChanged(BundleEvent event) { |
| events.add(event); |
| } |
| }; |
| getContext().addBundleListener(listener); |
| // register a higher ranked bundle EventHook that causes a bundle to resolve while processing INSTALLED events |
| ServiceRegistration<EventHook> bundleEventHook = getContext().registerService(EventHook.class, new EventHook() { |
| @Override |
| public void event(BundleEvent event, Collection<BundleContext> contexts) { |
| // force resolution if event is INSTALLED |
| if (event.getType() == BundleEvent.INSTALLED) { |
| getContext().getBundle(Constants.SYSTEM_BUNDLE_LOCATION).adapt(FrameworkWiring.class).resolveBundles(Collections.singleton(event.getBundle())); |
| } |
| } |
| }, new Hashtable<String, Object>(Collections.singletonMap(Constants.SERVICE_RANKING, Integer.MAX_VALUE))); |
| Bundle b = null; |
| try { |
| // install a bundle with no dependencies |
| b = bundleInstaller.installBundle(CP1); |
| b.start(); |
| } finally { |
| getContext().removeBundleListener(listener); |
| bundleEventHook.unregister(); |
| } |
| |
| for (int eventType : new int[] {BundleEvent.INSTALLED, BundleEvent.RESOLVED, BundleEvent.STARTING, BundleEvent.STARTED}) { |
| if (events.isEmpty()) { |
| fail("No events left, expecting event: " + eventType); |
| } |
| BundleEvent event = events.remove(0); |
| assertEquals("Wrong event type.", eventType, event.getType()); |
| assertEquals("Wrong bundle.", b, event.getBundle()); |
| } |
| } |
| |
| } |