diff options
author | Anjum Fatima | 2019-08-20 20:54:44 +0000 |
---|---|---|
committer | Anjum Fatima | 2019-08-20 20:54:44 +0000 |
commit | 4969d3557460a6d96ad985de999ee68b7f8700d1 (patch) | |
tree | 45e823981a69da8d198c4c8fb1e30e4937644afd | |
parent | 212756c289fccaa47aac82ad584bcf7521642f64 (diff) | |
download | rt.equinox.framework-4969d3557460a6d96ad985de999ee68b7f8700d1.tar.gz rt.equinox.framework-4969d3557460a6d96ad985de999ee68b7f8700d1.tar.xz rt.equinox.framework-4969d3557460a6d96ad985de999ee68b7f8700d1.zip |
Bug 549947 - Provide consistent ordering for callingY20190829-0900Y20190826-1000Y20190822-0900S4_13_0_RC1S4_13_0_M3I20190830-0550I20190830-0440I20190828-1800I20190828-0600I20190827-1800I20190827-0600I20190826-1800I20190826-0640I20190826-0415I20190823-0840I20190823-0530I20190821-1800
service/bundle/framework listeners
Change-Id: I8dffb2bf4b8d00d5778b778c6f4f54cbe9ec6667
Signed-off-by: Anjum Fatima <anjum.eclipse@gmail.com>
7 files changed, 350 insertions, 98 deletions
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/AbstractBundleTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/AbstractBundleTests.java index fc5a0a2eb..35b968f4e 100644 --- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/AbstractBundleTests.java +++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/AbstractBundleTests.java @@ -13,9 +13,24 @@ *******************************************************************************/ package org.eclipse.osgi.tests.bundles; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.jar.Attributes; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; import org.eclipse.core.tests.harness.CoreTest; +import org.eclipse.osgi.launch.Equinox; import org.eclipse.osgi.tests.OSGiTestsActivator; -import org.osgi.framework.*; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleEvent; +import org.osgi.framework.BundleException; +import org.osgi.framework.Constants; +import org.osgi.framework.FrameworkEvent; public class AbstractBundleTests extends CoreTest { public static int BUNDLE_LISTENER = 0x01; @@ -28,6 +43,36 @@ public class AbstractBundleTests extends CoreTest { public static EventListenerTestResults frameworkListenerResults; public static BundleInstaller installer; + static class BundleBuilder { + static class BundleManifestBuilder { + private final Manifest manifest = new Manifest(); + + public Manifest build() { + manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); + return manifest; + } + + public BundleManifestBuilder symbolicName(String value) { + manifest.getMainAttributes().putValue(Constants.BUNDLE_SYMBOLICNAME, value); + return this; + } + } + + private final BundleManifestBuilder manifestBuilder = new BundleManifestBuilder(); + + public InputStream build() throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JarOutputStream jos = new JarOutputStream(baos, manifestBuilder.build()); + jos.close(); + return new ByteArrayInputStream(baos.toByteArray()); + } + + public BundleBuilder symbolicName(String value) { + manifestBuilder.symbolicName(value); + return this; + } + } + protected void setUp() throws Exception { installer = new BundleInstaller(BUNDLES_ROOT, OSGiTestsActivator.getContext()); installer.refreshPackages(null); @@ -210,4 +255,27 @@ public class AbstractBundleTests extends CoreTest { return result.toString(); } + protected Map<String, Object> createConfiguration() { + File file = OSGiTestsActivator.getContext().getDataFile(getName()); + Map<String, Object> result = new HashMap<String, Object>(); + result.put(Constants.FRAMEWORK_STORAGE, file.getAbsolutePath()); + return result; + } + + protected void initAndStart(Equinox equinox) throws BundleException { + equinox.init(); + equinox.start(); + } + + protected void stopQuietly(Equinox equinox) { + if (equinox == null) + return; + try { + equinox.stop(); + equinox.waitForStop(5000); + } catch (Exception e) { + // Ignore + } + } + }
\ No newline at end of file diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/BundleTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/BundleTests.java index 5b04ee49f..0b497d5ba 100644 --- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/BundleTests.java +++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/BundleTests.java @@ -36,6 +36,7 @@ public class BundleTests { suite.addTest(ClassLoadingBundleTests.suite()); suite.addTest(NativeCodeBundleTests.suite()); suite.addTest(PlatformAdminBundleTests.suite()); + suite.addTest(ListenerTests.suite()); return suite; } } diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/DiscardBundleTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/DiscardBundleTests.java index 35aee2deb..0908f9227 100644 --- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/DiscardBundleTests.java +++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/DiscardBundleTests.java @@ -13,15 +13,20 @@ *******************************************************************************/ package org.eclipse.osgi.tests.bundles; -import java.io.*; -import java.util.HashMap; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; import java.util.Map; -import java.util.jar.*; +import java.util.jar.Attributes; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; import junit.framework.Test; import junit.framework.TestSuite; import org.eclipse.osgi.launch.Equinox; import org.eclipse.osgi.tests.OSGiTestsActivator; -import org.osgi.framework.*; +import org.osgi.framework.BundleException; +import org.osgi.framework.Constants; +import org.osgi.framework.FrameworkEvent; /* * The framework must discard a persisted bundle when the @@ -155,13 +160,6 @@ public class DiscardBundleTests extends AbstractBundleTests { return manifest; } - private Map<String, Object> createConfiguration() { - File file = OSGiTestsActivator.getContext().getDataFile(getName()); - Map<String, Object> result = new HashMap<String, Object>(); - result.put(Constants.FRAMEWORK_STORAGE, file.getAbsolutePath()); - return result; - } - private void doTest(Map<String, ?> configuration, boolean discard) throws Exception { doTest(configuration, discard, getDirectoryLocation()); doTest(configuration, discard, getJarLocation()); @@ -206,11 +204,6 @@ public class DiscardBundleTests extends AbstractBundleTests { return new File(root, BUNDLE_JAR); } - private void initAndStart(Equinox equinox) throws BundleException { - equinox.init(); - equinox.start(); - } - private Equinox restart(Equinox equinox, Map<String, ?> configuration) throws BundleException, InterruptedException { stop(equinox); equinox = new Equinox(configuration); @@ -224,17 +217,6 @@ public class DiscardBundleTests extends AbstractBundleTests { assertEquals("The framework was not stopped", FrameworkEvent.STOPPED, event.getType()); } - private void stopQuietly(Equinox equinox) { - if (equinox == null) - return; - try { - equinox.stop(); - equinox.waitForStop(5000); - } catch (Exception e) { - // Ignore - } - } - private void touchFile(File file) { if (file.isDirectory()) file = new File(file, BUNDLE_MANIFEST); diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/ListenerTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/ListenerTests.java new file mode 100644 index 000000000..7b693d9e7 --- /dev/null +++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/ListenerTests.java @@ -0,0 +1,227 @@ +/******************************************************************************* + * Copyright (c) 2019 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.osgi.tests.bundles; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import junit.framework.Test; +import junit.framework.TestSuite; +import org.eclipse.osgi.launch.Equinox; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleEvent; +import org.osgi.framework.BundleException; +import org.osgi.framework.BundleListener; +import org.osgi.framework.FrameworkEvent; +import org.osgi.framework.FrameworkListener; +import org.osgi.framework.ServiceEvent; +import org.osgi.framework.ServiceListener; +import org.osgi.framework.ServiceRegistration; +import org.osgi.framework.SynchronousBundleListener; +import org.osgi.framework.startlevel.FrameworkStartLevel; + +public class ListenerTests extends AbstractBundleTests { + + private String methodName; + private List<Bundle> bundles; + private Equinox equinox; + private BundleContext bundleContext; + + public static Test suite() { + return new TestSuite(ListenerTests.class); + } + + public void setUp() throws Exception { + methodName = getName(); + simpleResults = new TestResults(); + bundles = new ArrayList<>(); + + Map<String, Object> configuration = createConfiguration(); + equinox = new Equinox(configuration); + initAndStart(equinox); + + bundleContext = equinox.getBundleContext(); + + for (int i = 0; i < 50; i++) { + Bundle b = installBundle(methodName + i); + bundles.add(b); + b.start(); + } + } + + public void tearDown() throws Exception { + simpleResults = null; + for (Bundle b : bundles) { + if (b != null) { + b.stop(); + b = null; + } + } + stopQuietly(equinox); + } + + public void testBundleListenersOrder() throws Exception { + + BundleListener[] expectedBundleListeners = new BundleListener[200]; + + int i = 100; + for (Bundle b : bundles) { + BundleListener bundleListener = createBundleListener(); + b.getBundleContext().addBundleListener(bundleListener); + expectedBundleListeners[i] = bundleListener; + i = i + 2; + } + + int j = 101; + for (Bundle b : bundles) { + BundleListener bundleListener = createBundleListener(); + b.getBundleContext().addBundleListener(bundleListener); + expectedBundleListeners[j] = bundleListener; + j = j + 2; + } + + //synchronous listener will be called first + i = 0; + for (Bundle b : bundles) { + BundleListener bundleListener = createSynchronousBundleListener(); + b.getBundleContext().addBundleListener(bundleListener); + expectedBundleListeners[i] = bundleListener; + i = i + 2; + } + + j = 1; + for (Bundle b : bundles) { + BundleListener bundleListener = createSynchronousBundleListener(); + b.getBundleContext().addBundleListener(bundleListener); + expectedBundleListeners[j] = bundleListener; + j = j + 2; + } + + installBundle(methodName + "51"); + + Object[] actualBundleListeners = simpleResults.getResults(200); + + compareResults(expectedBundleListeners, actualBundleListeners); + + } + + public void testFrameworkListenersOrder() throws Exception { + FrameworkListener[] expectedFrameworkListeners = new FrameworkListener[100]; + + int i = 0; + for (Bundle b : bundles) { + FrameworkListener frameworkListener = createFrameworkListener(); + b.getBundleContext().addFrameworkListener(frameworkListener); + expectedFrameworkListeners[i] = frameworkListener; + i = i + 2; + } + + int j = 1; + for (Bundle b : bundles) { + FrameworkListener frameworkListener = createFrameworkListener(); + b.getBundleContext().addFrameworkListener(frameworkListener); + expectedFrameworkListeners[j] = frameworkListener; + j = j + 2; + } + + equinox.adapt(FrameworkStartLevel.class).setStartLevel(5); + + Object[] actualFrameworkListeners = simpleResults.getResults(100); + + compareResults(expectedFrameworkListeners, actualFrameworkListeners); + } + + public void testServiceListenersOrder() throws Exception { + ServiceListener[] expectedServiceListeners = new ServiceListener[100]; + + int i = 0; + for (Bundle b : bundles) { + ServiceListener serviceListener = createServiceListener(); + b.getBundleContext().addServiceListener(serviceListener); + expectedServiceListeners[i] = serviceListener; + i = i + 2; + } + + int j = 1; + for (Bundle b : bundles) { + ServiceListener serviceListener = createServiceListener(); + b.getBundleContext().addServiceListener(serviceListener); + expectedServiceListeners[j] = serviceListener; + j = j + 2; + } + + Bundle bundle = installBundle(methodName + "51"); + bundle.start(); + ServiceRegistration<Object> reg = bundle.getBundleContext().registerService(Object.class, new Object(), null); + + Object[] actualServiceListeners = simpleResults.getResults(100); + + compareResults(expectedServiceListeners, actualServiceListeners); + + if (reg != null) { + reg.unregister(); + } + + } + + private BundleListener createBundleListener() { + + BundleListener bundleListener = new BundleListener() { + public void bundleChanged(BundleEvent event) { + simpleResults.addEvent(this); + } + }; + return bundleListener; + } + + private BundleListener createSynchronousBundleListener() { + + SynchronousBundleListener bundleListener = new SynchronousBundleListener() { + public void bundleChanged(BundleEvent event) { + simpleResults.addEvent(this); + } + }; + return bundleListener; + } + + private FrameworkListener createFrameworkListener() { + FrameworkListener frameworkListener = new FrameworkListener() { + @Override + public void frameworkEvent(FrameworkEvent event) { + simpleResults.addEvent(this); + } + }; + return frameworkListener; + } + + private ServiceListener createServiceListener() { + ServiceListener serviceListener = new ServiceListener() { + + @Override + public void serviceChanged(ServiceEvent event) { + simpleResults.addEvent(this); + } + }; + return serviceListener; + } + + private Bundle installBundle(String name) throws BundleException, IOException { + Bundle bundle = bundleContext.installBundle(name, new BundleBuilder().symbolicName(name).build()); + assertNotNull(name + " bundle does not exist", bundleContext.getBundle(name)); + return bundle; + } + +}
\ No newline at end of file diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/PersistedBundleTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/PersistedBundleTests.java index 3d5225989..eb40f940e 100755 --- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/PersistedBundleTests.java +++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/PersistedBundleTests.java @@ -13,16 +13,10 @@ *******************************************************************************/ package org.eclipse.osgi.tests.bundles; -import java.io.*; -import java.util.HashMap; import java.util.Map; -import java.util.jar.*; import junit.framework.Test; import junit.framework.TestSuite; import org.eclipse.osgi.launch.Equinox; -import org.eclipse.osgi.tests.OSGiTestsActivator; -import org.osgi.framework.BundleException; -import org.osgi.framework.Constants; /* * The framework must persist data according to the value of the @@ -35,35 +29,6 @@ import org.osgi.framework.Constants; * */ public class PersistedBundleTests extends AbstractBundleTests { - static class BundleBuilder { - static class BundleManifestBuilder { - private final Manifest manifest = new Manifest(); - - public Manifest build() { - manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); - return manifest; - } - - public BundleManifestBuilder symbolicName(String value) { - manifest.getMainAttributes().putValue(Constants.BUNDLE_SYMBOLICNAME, value); - return this; - } - } - - private final BundleManifestBuilder manifestBuilder = new BundleManifestBuilder(); - - public InputStream build() throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - JarOutputStream jos = new JarOutputStream(baos, manifestBuilder.build()); - jos.close(); - return new ByteArrayInputStream(baos.toByteArray()); - } - - public BundleBuilder symbolicName(String value) { - manifestBuilder.symbolicName(value); - return this; - } - } private static final String ECLIPSE_STATESAVEDELAYINTERVAL = "eclipse.stateSaveDelayInterval"; @@ -185,26 +150,4 @@ public class PersistedBundleTests extends AbstractBundleTests { } } - private Map<String, Object> createConfiguration() { - File file = OSGiTestsActivator.getContext().getDataFile(getName()); - Map<String, Object> result = new HashMap<String, Object>(); - result.put(Constants.FRAMEWORK_STORAGE, file.getAbsolutePath()); - return result; - } - - private void initAndStart(Equinox equinox) throws BundleException { - equinox.init(); - equinox.start(); - } - - private void stopQuietly(Equinox equinox) { - if (equinox == null) - return; - try { - equinox.stop(); - equinox.waitForStop(5000); - } catch (Exception e) { - // Ignore - } - } }
\ No newline at end of file diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxEventPublisher.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxEventPublisher.java index 064983f21..19daba488 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxEventPublisher.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxEventPublisher.java @@ -18,6 +18,7 @@ import java.security.PrivilegedAction; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import java.util.concurrent.CountDownLatch; @@ -65,13 +66,13 @@ public class EquinoxEventPublisher { * installed in the Framework. */ // Map of BundleContexts for bundle's BundleListeners. - private final Map<BundleContextImpl, CopyOnWriteIdentityMap<BundleListener, BundleListener>> allBundleListeners = new HashMap<>(); + private final Map<BundleContextImpl, CopyOnWriteIdentityMap<BundleListener, BundleListener>> allBundleListeners = new LinkedHashMap<>(); // Map of BundleContexts for bundle's SynchronousBundleListeners. - private final Map<BundleContextImpl, CopyOnWriteIdentityMap<SynchronousBundleListener, SynchronousBundleListener>> allSyncBundleListeners = new HashMap<>(); + private final Map<BundleContextImpl, CopyOnWriteIdentityMap<SynchronousBundleListener, SynchronousBundleListener>> allSyncBundleListeners = new LinkedHashMap<>(); // Map of BundleContexts for bundle's FrameworkListeners. - private final Map<BundleContextImpl, CopyOnWriteIdentityMap<FrameworkListener, FrameworkListener>> allFrameworkListeners = new HashMap<>(); + private final Map<BundleContextImpl, CopyOnWriteIdentityMap<FrameworkListener, FrameworkListener>> allFrameworkListeners = new LinkedHashMap<>(); public EquinoxEventPublisher(EquinoxContainer container) { this.container = container; @@ -163,7 +164,7 @@ public class EquinoxEventPublisher { BundleContextImpl systemContext = null; Set<Map.Entry<SynchronousBundleListener, SynchronousBundleListener>> systemBundleListenersSync = null; synchronized (allSyncBundleListeners) { - listenersSync = new HashMap<>(allSyncBundleListeners.size()); + listenersSync = new LinkedHashMap<>(allSyncBundleListeners.size()); for (Map.Entry<BundleContextImpl, CopyOnWriteIdentityMap<SynchronousBundleListener, SynchronousBundleListener>> entry : allSyncBundleListeners.entrySet()) { CopyOnWriteIdentityMap<SynchronousBundleListener, SynchronousBundleListener> listeners = entry.getValue(); if (!listeners.isEmpty()) { @@ -183,7 +184,7 @@ public class EquinoxEventPublisher { Set<Map.Entry<BundleListener, BundleListener>> systemBundleListenersAsync = null; if ((event.getType() & (BundleEvent.STARTING | BundleEvent.STOPPING | BundleEvent.LAZY_ACTIVATION)) == 0) { synchronized (allBundleListeners) { - listenersAsync = new HashMap<>(allBundleListeners.size()); + listenersAsync = new LinkedHashMap<>(allBundleListeners.size()); for (Map.Entry<BundleContextImpl, CopyOnWriteIdentityMap<BundleListener, BundleListener>> entry : allBundleListeners.entrySet()) { CopyOnWriteIdentityMap<BundleListener, BundleListener> listeners = entry.getValue(); if (!listeners.isEmpty()) { @@ -318,7 +319,7 @@ public class EquinoxEventPublisher { // Build the listener snapshot Map<BundleContextImpl, Set<Map.Entry<FrameworkListener, FrameworkListener>>> listenerSnapshot; synchronized (allFrameworkListeners) { - listenerSnapshot = new HashMap<>(allFrameworkListeners.size()); + listenerSnapshot = new LinkedHashMap<>(allFrameworkListeners.size()); for (Map.Entry<BundleContextImpl, CopyOnWriteIdentityMap<FrameworkListener, FrameworkListener>> entry : allFrameworkListeners.entrySet()) { CopyOnWriteIdentityMap<FrameworkListener, FrameworkListener> listeners = entry.getValue(); if (!listeners.isEmpty()) { diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceRegistry.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceRegistry.java index 5d4da714c..d53f3b246 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceRegistry.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceRegistry.java @@ -14,19 +14,49 @@ package org.eclipse.osgi.internal.serviceregistry; -import java.security.*; -import java.util.*; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.ProtectionDomain; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Dictionary; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; import org.eclipse.osgi.container.Module; import org.eclipse.osgi.container.ModuleRevision; -import org.eclipse.osgi.framework.eventmgr.*; +import org.eclipse.osgi.framework.eventmgr.CopyOnWriteIdentityMap; +import org.eclipse.osgi.framework.eventmgr.EventDispatcher; +import org.eclipse.osgi.framework.eventmgr.ListenerQueue; import org.eclipse.osgi.internal.debug.Debug; import org.eclipse.osgi.internal.framework.BundleContextImpl; import org.eclipse.osgi.internal.framework.EquinoxContainer; import org.eclipse.osgi.internal.messages.Msg; import org.eclipse.osgi.storage.BundleInfo.Generation; import org.eclipse.osgi.util.NLS; -import org.osgi.framework.*; -import org.osgi.framework.hooks.service.*; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.Filter; +import org.osgi.framework.FrameworkEvent; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceEvent; +import org.osgi.framework.ServiceException; +import org.osgi.framework.ServiceFactory; +import org.osgi.framework.ServiceListener; +import org.osgi.framework.ServiceObjects; +import org.osgi.framework.ServicePermission; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; +import org.osgi.framework.hooks.service.EventHook; +import org.osgi.framework.hooks.service.EventListenerHook; +import org.osgi.framework.hooks.service.FindHook; +import org.osgi.framework.hooks.service.ListenerHook; import org.osgi.framework.hooks.service.ListenerHook.ListenerInfo; /** @@ -97,7 +127,7 @@ public class ServiceRegistry { publishedServicesByClass = new HashMap<>(initialCapacity); publishedServicesByContext = new HashMap<>(initialCapacity); allPublishedServices = new ArrayList<>(initialCapacity); - serviceEventListeners = new HashMap<>(initialCapacity); + serviceEventListeners = new LinkedHashMap<>(initialCapacity); Module systemModule = container.getStorage().getModuleContainer().getModule(0); systemBundleContext = (BundleContextImpl) systemModule.getBundle().getBundleContext(); systemBundleContext.provisionServicesInUseMap(); @@ -819,7 +849,7 @@ public class ServiceRegistry { Set<Map.Entry<ServiceListener, FilteredServiceListener>> systemServiceListenersOrig = null; BundleContextImpl systemContext = null; synchronized (serviceEventListeners) { - listenerSnapshot = new HashMap<>(serviceEventListeners.size()); + listenerSnapshot = new LinkedHashMap<>(serviceEventListeners.size()); for (Map.Entry<BundleContextImpl, CopyOnWriteIdentityMap<ServiceListener, FilteredServiceListener>> entry : serviceEventListeners.entrySet()) { Map<ServiceListener, FilteredServiceListener> listeners = entry.getValue(); if (!listeners.isEmpty()) { |