More refactoring to service registry hook handling to match
byte-code weaving hook handling. (FELIX-2959)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1127267 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java b/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java
index e8014ea..e2a1464 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java
@@ -1366,7 +1366,7 @@
Set<ServiceReference<WeavingHook>> hooks =
felix.getHooks(WeavingHook.class);
WovenClassImpl wci = null;
- if ((hooks != null) && !hooks.isEmpty())
+ if (!hooks.isEmpty())
{
// Create woven class to be used for hooks.
wci = new WovenClassImpl(name, BundleWiringImpl.this, bytes);
diff --git a/framework/src/main/java/org/apache/felix/framework/Felix.java b/framework/src/main/java/org/apache/felix/framework/Felix.java
index 0dfcf10..a6e009d 100644
--- a/framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -606,8 +606,16 @@
m_activatorList = (List) m_configMutableMap.get(FelixConstants.SYSTEMBUNDLE_ACTIVATORS_PROP);
m_activatorList = (m_activatorList == null) ? new ArrayList() : new ArrayList(m_activatorList);
+ // Create service registry.
+ m_registry = new ServiceRegistry(m_logger, new ServiceRegistryCallbacks() {
+ public void serviceChanged(ServiceEvent event, Dictionary oldProps)
+ {
+ fireServiceEvent(event, oldProps);
+ }
+ });
+
// Initialize event dispatcher.
- m_dispatcher = EventDispatcher.start(m_logger);
+ m_dispatcher = EventDispatcher.start(m_logger, m_registry);
// Create the bundle cache, if necessary, so that we can reload any
// installed bundles.
@@ -742,15 +750,6 @@
// keep the max value.
m_nextId = Math.max(m_nextId, loadNextId());
- // Create service registry.
- m_registry = new ServiceRegistry(m_logger, new ServiceRegistryCallbacks() {
- public void serviceChanged(ServiceEvent event, Dictionary oldProps)
- {
- fireServiceEvent(event, oldProps);
- }
- });
- m_dispatcher.setServiceRegistry(m_registry);
-
// The framework is now in its startup sequence.
setBundleStateAndNotify(this, Bundle.STARTING);
@@ -2904,26 +2903,50 @@
final Collection removed = Collections.singleton(
new ListenerHookInfoImpl(
((BundleImpl) bundle)._getBundleContext(), l, oldFilter.toString(), true));
- InvokeHookCallback removedCallback = new ListenerHookRemovedCallback(removed);
for (ServiceReference<ListenerHook> sr : listenerHooks)
{
- m_registry.invokeHook(sr, this, removedCallback);
+ ListenerHook lh = m_registry.getServiceSafely(this, sr);
+ if (lh != null)
+ {
+ try
+ {
+ lh.removed(removed);
+ }
+ catch (Throwable th)
+ {
+ m_logger.log(sr, Logger.LOG_WARNING,
+ "Problem invoking service registry hook", th);
+ }
+ finally
+ {
+ m_registry.ungetService(this, sr);
+ }
+ }
}
}
// Invoke the ListenerHook.added() on all hooks.
final Collection added = Collections.singleton(
new ListenerHookInfoImpl(((BundleImpl) bundle)._getBundleContext(), l, f, false));
- InvokeHookCallback addedCallback = new InvokeHookCallback()
- {
- public void invokeHook(Object hook)
- {
- ((ListenerHook) hook).added(added);
- }
- };
for (ServiceReference<ListenerHook> sr : listenerHooks)
{
- m_registry.invokeHook(sr, this, addedCallback);
+ ListenerHook lh = m_registry.getServiceSafely(this, sr);
+ if (lh != null)
+ {
+ try
+ {
+ lh.added(added);
+ }
+ catch (Throwable th)
+ {
+ m_logger.log(sr, Logger.LOG_WARNING,
+ "Problem invoking service registry hook", th);
+ }
+ finally
+ {
+ m_registry.ungetService(this, sr);
+ }
+ }
}
}
@@ -2944,11 +2967,26 @@
// Invoke the ListenerHook.removed() on all hooks.
Set<ServiceReference<ListenerHook>> listenerHooks =
m_registry.getHooks(ListenerHook.class);
- Collection c = Collections.singleton(listener);
- InvokeHookCallback callback = new ListenerHookRemovedCallback(c);
+ Collection removed = Collections.singleton(listener);
for (ServiceReference<ListenerHook> sr : listenerHooks)
{
- m_registry.invokeHook(sr, this, callback);
+ ListenerHook lh = m_registry.getServiceSafely(this, sr);
+ if (lh != null)
+ {
+ try
+ {
+ lh.removed(removed);
+ }
+ catch (Throwable th)
+ {
+ m_logger.log(sr, Logger.LOG_WARNING,
+ "Problem invoking service registry hook", th);
+ }
+ finally
+ {
+ m_registry.ungetService(this, sr);
+ }
+ }
}
}
}
@@ -3053,14 +3091,23 @@
// to invoke the callback with all existing service listeners.
if (ServiceRegistry.isHook(classNames, ListenerHook.class, svcObj))
{
- m_registry.invokeHook(reg.getReference(), this, new InvokeHookCallback()
+ ListenerHook lh = (ListenerHook) m_registry.getServiceSafely(this, reg.getReference());
+ if (lh != null)
{
- public void invokeHook(Object hook)
+ try
{
- ((ListenerHook) hook).
- added(m_dispatcher.wrapAllServiceListeners(false));
+ lh.added(m_dispatcher.wrapAllServiceListeners(false));
}
- });
+ catch (Throwable th)
+ {
+ m_logger.log(reg.getReference(), Logger.LOG_WARNING,
+ "Problem invoking service registry hook", th);
+ }
+ finally
+ {
+ m_registry.ungetService(this, reg.getReference());
+ }
+ }
}
// TODO: CONCURRENCY - Reconsider firing event here, outside of the
@@ -3125,20 +3172,29 @@
// activate findhooks
Set<ServiceReference<FindHook>> findHooks =
m_registry.getHooks(FindHook.class);
- InvokeHookCallback callback = new InvokeHookCallback()
- {
- public void invokeHook(Object hook)
- {
- ((FindHook) hook).find(bundle._getBundleContext(),
- className,
- expr,
- !checkAssignable,
- new ShrinkableCollection(refList));
- }
- };
for (ServiceReference<FindHook> sr : findHooks)
{
- m_registry.invokeHook(sr, this, callback);
+ FindHook fh = m_registry.getServiceSafely(this, sr);
+ if (fh != null)
+ {
+ try
+ {
+ fh.find(bundle._getBundleContext(),
+ className,
+ expr,
+ !checkAssignable,
+ new ShrinkableCollection(refList));
+ }
+ catch (Throwable th)
+ {
+ m_logger.log(sr, Logger.LOG_WARNING,
+ "Problem invoking service registry hook", th);
+ }
+ finally
+ {
+ m_registry.ungetService(this, sr);
+ }
+ }
}
if (refList.size() > 0)
@@ -4992,21 +5048,6 @@
}
}
- private static class ListenerHookRemovedCallback implements InvokeHookCallback
- {
- private final Collection /* ListenerHookInfo */ m_removed;
-
- ListenerHookRemovedCallback(Collection /* ListenerHookInfo */ removed)
- {
- m_removed = removed;
- }
-
- public void invokeHook(Object hook)
- {
- ((ListenerHook) hook).removed(m_removed);
- }
- }
-
// Compares bundles by start level. Within a start level,
// bundles are sorted by bundle ID.
private static class StartLevelTuple implements Comparable<StartLevelTuple>
diff --git a/framework/src/main/java/org/apache/felix/framework/InvokeHookCallback.java b/framework/src/main/java/org/apache/felix/framework/InvokeHookCallback.java
deleted file mode 100644
index 62dde99..0000000
--- a/framework/src/main/java/org/apache/felix/framework/InvokeHookCallback.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.felix.framework;
-
-public interface InvokeHookCallback
-{
- void invokeHook(Object hook);
-}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java b/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java
index 98d6026..fe0a079 100644
--- a/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java
+++ b/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java
@@ -238,7 +238,20 @@
return null;
}
- public Object getService(Bundle bundle, ServiceReference ref)
+ public <S> S getServiceSafely(Bundle bundle, ServiceReference<S> ref)
+ {
+ try
+ {
+ return getService(bundle, ref);
+ }
+ catch (ServiceException ex)
+ {
+ // Just ignore and return null.
+ }
+ return null;
+ }
+
+ public <S> S getService(Bundle bundle, ServiceReference<S> ref)
{
UsageCount usage = null;
Object svcObj = null;
@@ -331,7 +344,7 @@
}
}
- return svcObj;
+ return (S) svcObj;
}
public boolean ungetService(Bundle bundle, ServiceReference ref)
@@ -757,34 +770,6 @@
return (SortedSet<ServiceReference<S>>) (SortedSet) ss;
}
- /**
- * Invokes a Service Registry Hook
- * @param ref The ServiceReference associated with the hook to be invoked, the hook
- * service object will be obtained through this object.
- * @param framework The framework that is invoking the hook, typically the Felix object.
- * @param callback This is a callback object that is invoked with the actual hook object to
- * be used, either the plain hook, or one obtained from the ServiceFactory.
- */
- public void invokeHook(
- ServiceReference ref, Framework framework, InvokeHookCallback callback)
- {
- Object hook = getService(framework, ref);
-
- try
- {
- callback.invokeHook(hook);
- }
- catch (Throwable th)
- {
- m_logger.log(ref, Logger.LOG_WARNING,
- "Problem invoking Service Registry Hook", th);
- }
- finally
- {
- ungetService(framework, ref);
- }
- }
-
private static class UsageCount
{
public int m_count = 0;
diff --git a/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java b/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java
index 6b7c8a1..c77ee55 100644
--- a/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java
+++ b/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java
@@ -30,7 +30,6 @@
import java.util.NoSuchElementException;
import java.util.Set;
-import org.apache.felix.framework.InvokeHookCallback;
import org.apache.felix.framework.Logger;
import org.apache.felix.framework.ServiceRegistry;
import org.osgi.framework.AllServiceListener;
@@ -60,7 +59,7 @@
static final int LISTENER_ARRAY_INCREMENT = 5;
private final Logger m_logger;
- private volatile ServiceRegistry m_serviceRegistry = null;
+ private final ServiceRegistry m_registry;
// Representation of an empty listener list.
private static final Object[] m_emptyList = new Object[0];
@@ -81,14 +80,15 @@
// Pooled requests to avoid memory allocation.
private static final ArrayList m_requestPool = new ArrayList();
- private EventDispatcher(Logger logger)
+ private EventDispatcher(Logger logger, ServiceRegistry registry)
{
m_logger = logger;
+ m_registry = registry;
}
- public static EventDispatcher start(Logger logger)
+ public static EventDispatcher start(Logger logger, ServiceRegistry registry)
{
- EventDispatcher eventDispatcher = new EventDispatcher(logger);
+ EventDispatcher eventDispatcher = new EventDispatcher(logger, registry);
synchronized (m_threadLock)
{
@@ -128,11 +128,6 @@
return eventDispatcher;
}
- public void setServiceRegistry(ServiceRegistry sr)
- {
- m_serviceRegistry = sr;
- }
-
public static void shutdown()
{
synchronized (m_threadLock)
@@ -630,31 +625,36 @@
listeners = m_serviceListeners;
}
- if (m_serviceRegistry != null)
+ Set<ServiceReference<EventHook>> eventHooks = m_registry.getHooks(EventHook.class);
+ if ((eventHooks != null) && !eventHooks.isEmpty())
{
- Set<ServiceReference<EventHook>> eventHooks =
- m_serviceRegistry.getHooks(EventHook.class);
- if ((eventHooks != null) && !eventHooks.isEmpty())
+ final ListenerBundleContextCollectionWrapper wrapper =
+ new ListenerBundleContextCollectionWrapper(listeners);
+ for (ServiceReference<EventHook> sr : eventHooks)
{
- final ListenerBundleContextCollectionWrapper wrapper =
- new ListenerBundleContextCollectionWrapper(listeners);
- InvokeHookCallback callback = new InvokeHookCallback()
+ if (felix != null)
{
- public void invokeHook(Object hook)
+ EventHook eh = m_registry.getServiceSafely(felix, sr);
+ if (eh != null)
{
- ((EventHook) hook).event(event, wrapper);
- }
- };
- for (ServiceReference<EventHook> sr : eventHooks)
- {
- if (felix != null)
- {
- m_serviceRegistry.invokeHook(sr, felix, callback);
+ try
+ {
+ eh.event(event, wrapper);
+ }
+ catch (Throwable th)
+ {
+ m_logger.log(sr, Logger.LOG_WARNING,
+ "Problem invoking service registry hook", th);
+ }
+ finally
+ {
+ m_registry.ungetService(felix, sr);
+ }
}
}
-
- listeners = wrapper.getListeners();
}
+
+ listeners = wrapper.getListeners();
}
// Fire all service events immediately on the calling thread.
diff --git a/framework/src/test/java/org/apache/felix/framework/ServiceRegistryTest.java b/framework/src/test/java/org/apache/felix/framework/ServiceRegistryTest.java
index ac1c25d..c8c8a9e 100644
--- a/framework/src/test/java/org/apache/felix/framework/ServiceRegistryTest.java
+++ b/framework/src/test/java/org/apache/felix/framework/ServiceRegistryTest.java
@@ -18,10 +18,8 @@
*/
package org.apache.felix.framework;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable;
-import java.util.List;
import junit.framework.TestCase;
@@ -35,7 +33,6 @@
import org.osgi.framework.hooks.service.EventHook;
import org.osgi.framework.hooks.service.FindHook;
import org.osgi.framework.hooks.service.ListenerHook;
-import org.osgi.framework.launch.Framework;
public class ServiceRegistryTest extends TestCase
{
@@ -294,95 +291,4 @@
assertEquals("Unregistration should have no effect", 0, sr.getHooks(FindHook.class).size());
assertEquals("Unregistration should have no effect", 0, sr.getHooks(ListenerHook.class).size());
}
-
- public void testInvokeHook()
- {
- ServiceRegistry sr = new ServiceRegistry(null, null);
-
- final List result = new ArrayList();
- InvokeHookCallback callback = new InvokeHookCallback()
- {
- public void invokeHook(Object hook)
- {
- result.add(hook);
- }
- };
-
- MockControl control = MockControl.createNiceControl(Framework.class);
- Framework fr = (Framework) control.getMock();
- control.replay();
-
- FindHook hook = new FindHook()
- {
- public void find(BundleContext context, String name, String filter,
- boolean allServices, Collection references)
- {
- }
- };
- ServiceRegistration reg = new ServiceRegistrationImpl(sr, null, null, null,
- hook, new Hashtable());
-
- assertEquals("Precondition failed", 0, result.size());
- sr.invokeHook(reg.getReference(), fr, callback);
- assertEquals(1, result.size());
- assertSame(hook, result.iterator().next());
- }
-
- public void testInvokeHookFactory()
- {
- ServiceRegistry sr = new ServiceRegistry(null, null);
-
- final List result = new ArrayList();
- InvokeHookCallback callback = new InvokeHookCallback()
- {
- public void invokeHook(Object hook)
- {
- result.add(hook);
- }
- };
-
- MockControl control = MockControl.createNiceControl(Framework.class);
- Framework fr = (Framework) control.getMock();
- control.replay();
-
- final FindHook hook = new FindHook()
- {
- public void find(BundleContext context, String name, String filter,
- boolean allServices, Collection references)
- {
- }
- };
-
- final List sfGet = new ArrayList();
- final List sfUnget = new ArrayList();
- ServiceFactory sf = new ServiceFactory()
- {
- public Object getService(Bundle b, ServiceRegistration reg)
- {
- sfGet.add(reg);
- return hook;
- }
-
- public void ungetService(Bundle b, ServiceRegistration reg, Object svcObj)
- {
- sfUnget.add(reg);
- assertSame(svcObj, hook);
- }
- };
-
- ServiceRegistration reg = new ServiceRegistrationImpl(sr, null,
- new String[] {FindHook.class.getName()}, null,
- sf, new Hashtable());
-
- assertEquals("Precondition failed", 0, result.size());
- assertEquals("Precondition failed", 0, sfGet.size());
- assertEquals("Precondition failed", 0, sfUnget.size());
- sr.invokeHook(reg.getReference(), fr, callback);
- assertEquals(1, result.size());
- assertSame(hook, result.iterator().next());
- assertEquals(1, sfGet.size());
- assertEquals(1, sfUnget.size());
- assertSame(reg, sfGet.iterator().next());
- assertSame(reg, sfUnget.iterator().next());
- }
}
diff --git a/framework/src/test/java/org/apache/felix/framework/util/EventDispatcherTest.java b/framework/src/test/java/org/apache/felix/framework/util/EventDispatcherTest.java
index 3dff2c5..1c04eb5 100644
--- a/framework/src/test/java/org/apache/felix/framework/util/EventDispatcherTest.java
+++ b/framework/src/test/java/org/apache/felix/framework/util/EventDispatcherTest.java
@@ -83,9 +83,8 @@
registry.registerService(null, new String [] {EventHook.class.getName()}, eh2, new Hashtable());
// -- Set up event dispatcher
- EventDispatcher ed = EventDispatcher.start(logger);
+ EventDispatcher ed = EventDispatcher.start(logger, registry);
EventDispatcher.shutdown(); // stop the thread - would be nicer if we could create one without a thread for testing
- ed.setServiceRegistry(registry);
// -- Register some listeners
final List fired = Collections.synchronizedList(new ArrayList());