diff options
7 files changed, 108 insertions, 111 deletions
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/BundleContextImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/BundleContextImpl.java index 8c8a8249a..320d68957 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/BundleContextImpl.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/BundleContextImpl.java @@ -72,7 +72,6 @@ import org.osgi.resource.Capability; */ public class BundleContextImpl implements BundleContext, EventDispatcher<Object, Object, Object> { - static final String findHookName = FindHook.class.getName(); /** true if the bundle context is still valid */ private volatile boolean valid; @@ -258,10 +257,8 @@ public class BundleContextImpl implements BundleContext, EventDispatcher<Object, if (debug.DEBUG_HOOKS) { Debug.println("notifyBundleFindHooks(" + allBundles + ")"); //$NON-NLS-1$ //$NON-NLS-2$ } - container.getServiceRegistry().notifyHooksPrivileged(findHookName, "find", (hook, hookRegistration) -> { //$NON-NLS-1$ - if (hook instanceof FindHook) { - ((FindHook) hook).find(context, allBundles); - } + container.getServiceRegistry().notifyHooksPrivileged(FindHook.class, "find", (hook, hookRegistration) -> { //$NON-NLS-1$ + hook.find(context, allBundles); }); } 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 0e85e7031..71b167bce 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 @@ -38,12 +38,9 @@ import org.osgi.framework.BundleListener; import org.osgi.framework.FrameworkEvent; import org.osgi.framework.FrameworkListener; import org.osgi.framework.SynchronousBundleListener; -import org.osgi.framework.hooks.bundle.CollisionHook; import org.osgi.framework.hooks.bundle.EventHook; public class EquinoxEventPublisher { - static final String eventHookName = EventHook.class.getName(); - static final String collisionHookName = CollisionHook.class.getName(); @SuppressWarnings("deprecation") static final int FRAMEWORK_STOPPED_MASK = (FrameworkEvent.STOPPED | FrameworkEvent.STOPPED_BOOTCLASSPATH_MODIFIED | FrameworkEvent.STOPPED_UPDATE | FrameworkEvent.STOPPED_SYSTEM_REFRESHED); @@ -255,10 +252,8 @@ public class EquinoxEventPublisher { ServiceRegistry serviceRegistry = container.getServiceRegistry(); if (serviceRegistry != null) { - serviceRegistry.notifyHooksPrivileged(eventHookName, "event", (hook, hookRegistration) -> { //$NON-NLS-1$ - if (hook instanceof EventHook) { - ((EventHook) hook).event(event, result); - } + serviceRegistry.notifyHooksPrivileged(EventHook.class, "event", (hook, hookRegistration) -> { //$NON-NLS-1$ + hook.event(event, result); }); } } diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/OSGiFrameworkHooks.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/OSGiFrameworkHooks.java index 3dc90dab0..9fb875edf 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/OSGiFrameworkHooks.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/OSGiFrameworkHooks.java @@ -44,7 +44,6 @@ import org.osgi.framework.wiring.BundleRequirement; import org.osgi.framework.wiring.BundleRevision; class OSGiFrameworkHooks { - static final String collisionHookName = CollisionHook.class.getName(); private final CoreResolverHookFactory resolverHookFactory; private final ModuleCollisionHook collisionHook; @@ -117,10 +116,8 @@ class OSGiFrameworkHooks { } ServiceRegistry registry = container.getServiceRegistry(); if (registry != null) { - registry.notifyHooksPrivileged(collisionHookName, "filterCollisions", (hook, hookRegistration) -> { //$NON-NLS-1$ - if (hook instanceof CollisionHook) { - ((CollisionHook) hook).filterCollisions(operationType, target, collisionCandidates); - } + registry.notifyHooksPrivileged(CollisionHook.class, "filterCollisions", (hook, hookRegistration) -> { //$NON-NLS-1$ + hook.filterCollisions(operationType, target, collisionCandidates); }); } } diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/HookContext.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/HookContext.java index 29bead28a..de045bd59 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/HookContext.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/HookContext.java @@ -24,7 +24,7 @@ import org.osgi.framework.ServiceRegistration; * */ @FunctionalInterface -public interface HookContext { +public interface HookContext<T> { /** * Call the specified hook. @@ -35,7 +35,7 @@ public interface HookContext { * @param hookRegistration the registration for the hook object * @throws Exception An exception thrown by the hook object. */ - public void call(Object hook, ServiceRegistration<?> hookRegistration) throws Exception; + public void call(T hook, ServiceRegistration<T> hookRegistration) throws Exception; /** * Returns true if the given registration should be skipped. diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceRegistrationImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceRegistrationImpl.java index a0dc562b4..bdf4a0b45 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceRegistrationImpl.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceRegistrationImpl.java @@ -488,15 +488,6 @@ public class ServiceRegistrationImpl<S> implements ServiceRegistration<S>, Compa return bundle; } - S getSafeService(BundleContextImpl user, ServiceConsumer consumer) { - try { - return getService(user, consumer); - } catch (IllegalStateException e) { - // can happen if the user is stopped on another thread - return null; - } - } - /** * Get a service object for the using BundleContext. * @@ -779,11 +770,13 @@ public class ServiceRegistrationImpl<S> implements ServiceRegistration<S>, Compa private volatile S hookInstance; private final BundleContextImpl systemContext; private final Object hookLock = new Object(); + private final List<Class<?>> hookTypes; FrameworkHookRegistration(ServiceRegistry registry, BundleContextImpl context, String[] clazzes, S service, - BundleContextImpl systemContext) { + BundleContextImpl systemContext, List<Class<?>> hookTypes) { super(registry, context, clazzes, service); this.systemContext = systemContext; + this.hookTypes = hookTypes; } @Override @@ -814,5 +807,22 @@ public class ServiceRegistrationImpl<S> implements ServiceRegistration<S>, Compa systemContext.ungetService(getReferenceImpl()); } } + + S getSafeService(BundleContextImpl user, ServiceConsumer consumer) { + try { + S hook = getService(user, consumer); + if (hookTypes.stream().filter((hookType) -> !hookType.isInstance(hook)).findFirst().isPresent()) { + // the hook impl is wired to a different hook package than the framework + if (hook != null) { + systemContext.ungetService(getReference()); + } + return null; + } + return hook; + } catch (IllegalStateException e) { + // can happen if the user is stopped on another thread + return null; + } + } } } 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 1cb84dc37..2023bf232 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 @@ -68,10 +68,6 @@ import org.osgi.framework.hooks.service.ListenerHook.ListenerInfo; public class ServiceRegistry { public static final int SERVICEEVENT = 3; - static final String findHookName = FindHook.class.getName(); - @SuppressWarnings("deprecation") - static final String eventHookName = EventHook.class.getName(); - static final String eventListenerHookName = EventListenerHook.class.getName(); static final String listenerHookName = ListenerHook.class.getName(); @@ -231,15 +227,15 @@ public class ServiceRegistry { } boolean isListenerHook = false; - boolean isFrameworkHook = false; /* copy the array so that changes to the original will not affect us. */ List<String> copy = new ArrayList<>(size); + List<Class<?>> hookTypes = null; // intern the strings and remove duplicates for (int i = 0; i < size; i++) { String clazz = clazzes[i].intern(); if (!copy.contains(clazz)) { isListenerHook = isListenerHook || listenerHookName.equals(clazz); - isFrameworkHook = isFrameworkHook || isFrameworkHook(clazz); + hookTypes = getHookClass(clazz, hookTypes); copy.add(clazz); } } @@ -259,9 +255,9 @@ public class ServiceRegistry { } } - ServiceRegistrationImpl<?> registration = isFrameworkHook + ServiceRegistrationImpl<?> registration = hookTypes != null ? new ServiceRegistrationImpl.FrameworkHookRegistration<>(this, context, clazzes, service, - systemBundleContext) + systemBundleContext, hookTypes) : new ServiceRegistrationImpl<>(this, context, clazzes, service); registration.register(properties); registration.initHookInstance(); @@ -272,29 +268,38 @@ public class ServiceRegistry { return registration; } - private boolean isFrameworkHook(String className) { + @SuppressWarnings("deprecation") + private List<Class<?>> getHookClass(String className, List<Class<?>> hookTypes) { switch (className) { case "org.osgi.framework.hooks.bundle.CollisionHook": //$NON-NLS-1$ - return true; + return addHook(org.osgi.framework.hooks.bundle.CollisionHook.class, hookTypes); case "org.osgi.framework.hooks.bundle.EventHook": //$NON-NLS-1$ - return true; + return addHook(org.osgi.framework.hooks.bundle.EventHook.class, hookTypes); case "org.osgi.framework.hooks.bundle.FindHook": //$NON-NLS-1$ - return true; + return addHook(org.osgi.framework.hooks.bundle.FindHook.class, hookTypes); case "org.osgi.framework.hooks.service.EventHook": //$NON-NLS-1$ - return true; + return addHook(org.osgi.framework.hooks.service.EventHook.class, hookTypes); case "org.osgi.framework.hooks.service.EventListenerHook": //$NON-NLS-1$ - return true; + return addHook(org.osgi.framework.hooks.service.EventListenerHook.class, hookTypes); case "org.osgi.framework.hooks.service.FindHook": //$NON-NLS-1$ - return true; + return addHook(org.osgi.framework.hooks.service.FindHook.class, hookTypes); case "org.osgi.framework.hooks.service.ListenerHook": //$NON-NLS-1$ - return true; + return addHook(org.osgi.framework.hooks.service.ListenerHook.class, hookTypes); case "org.osgi.framework.hooks.weaving.WeavingHook": //$NON-NLS-1$ - return true; + return addHook(org.osgi.framework.hooks.weaving.WeavingHook.class, hookTypes); case "org.osgi.framework.hooks.weaving.WovenClassListener": //$NON-NLS-1$ - return true; + return addHook(org.osgi.framework.hooks.weaving.WovenClassListener.class, hookTypes); default: - return false; + return hookTypes; + } + } + + private List<Class<?>> addHook(Class<?> hookType, List<Class<?>> hookTypes) { + if (hookTypes == null) { + hookTypes = new ArrayList<>(1); } + hookTypes.add(hookType); + return hookTypes; } /** @@ -1245,10 +1250,8 @@ public class ServiceRegistry { if (debug.DEBUG_HOOKS) { Debug.println("notifyServiceFindHooks(" + context.getBundleImpl() + "," + clazz + "," + filterstring + "," + allservices + "," + result + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ } - notifyHooksPrivileged(findHookName, "find", (hook, hookRegistration) -> { //$NON-NLS-1$ - if (hook instanceof FindHook) { - ((FindHook) hook).find(context, clazz, filterstring, allservices, result); - } + notifyHooksPrivileged(FindHook.class, "find", (hook, hookRegistration) -> { //$NON-NLS-1$ + hook.find(context, clazz, filterstring, allservices, result); }); } @@ -1265,10 +1268,8 @@ public class ServiceRegistry { if (debug.DEBUG_HOOKS) { Debug.println("notifyServiceEventHooks(" + event.getType() + ":" + event.getServiceReference() + "," + result + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ } - notifyHooksPrivileged(eventHookName, "event", (hook, hookRegistration) -> { //$NON-NLS-1$ - if (hook instanceof EventHook) { - ((EventHook) hook).event(event, result); - } + notifyHooksPrivileged(EventHook.class, "event", (hook, hookRegistration) -> { //$NON-NLS-1$ + hook.event(event, result); }); } @@ -1284,41 +1285,45 @@ public class ServiceRegistry { if (debug.DEBUG_HOOKS) { Debug.println("notifyServiceEventListenerHooks(" + event.getType() + ":" + event.getServiceReference() + "," + result + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ } - notifyHooksPrivileged(eventListenerHookName, "event", (hook, hookRegistration) -> { //$NON-NLS-1$ - if (hook instanceof EventListenerHook) { - ((EventListenerHook) hook).event(event, result); - } + notifyHooksPrivileged(EventListenerHook.class, "event", (hook, hookRegistration) -> { //$NON-NLS-1$ + hook.event(event, result); }); } /** * Calls all hook services of the type specified by the hook context. + * + * @param <T> * * @param hookContext Context to use when calling the hook services. */ - public void notifyHooksPrivileged(String serviceName, String serviceMethod, HookContext hookContext) { - List<ServiceRegistrationImpl<?>> hooks = lookupServiceRegistrations(serviceName, null); + @SuppressWarnings("unchecked") + public <T> void notifyHooksPrivileged(Class<T> hookType, String serviceMethod, HookContext<T> hookContext) { + List<ServiceRegistrationImpl<?>> hooks = lookupServiceRegistrations(hookType.getName(), null); // Since the list is already sorted, we don't need to sort the list to call the hooks // in the proper order. for (ServiceRegistrationImpl<?> registration : hooks) { - notifyHookPrivileged(systemBundleContext, registration, serviceMethod, hookContext); + notifyHookPrivileged(systemBundleContext, (ServiceRegistrationImpl<T>) registration, serviceMethod, + hookContext); } } /** * Call a hook service via a hook context. + * + * @param <T> * - * @param context Context of the bundle to get the hook service. + * @param context Context of the bundle to get the hook service. * @param registration Hook service to call. - * @param hookContext Context to use when calling the hook service. + * @param hookContext Context to use when calling the hook service. */ - private void notifyHookPrivileged(BundleContextImpl context, ServiceRegistrationImpl<?> registration, - String serviceMethod, HookContext hookContext) { + private <T> void notifyHookPrivileged(BundleContextImpl context, ServiceRegistrationImpl<T> registration, + String serviceMethod, HookContext<T> hookContext) { if (hookContext.skipRegistration(registration)) { return; } - Object hook = registration.getHookInstance(); + T hook = registration.getHookInstance(); if (hook == null) { // The hook may not be initialized yet // We do not call the hook until after it has been registered @@ -1415,13 +1420,11 @@ public class ServiceRegistry { Debug.println("notifyServiceListenerHooks(" + listeners + "," + (added ? "added" : "removed") + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ } - notifyHooksPrivileged(listenerHookName, added ? "added" : "removed", (hook, hookRegistration) -> { //$NON-NLS-1$ //$NON-NLS-2$ - if (hook instanceof ListenerHook) { - if (added) { - ((ListenerHook) hook).added(listeners); - } else { - ((ListenerHook) hook).removed(listeners); - } + notifyHooksPrivileged(ListenerHook.class, added ? "added" : "removed", (hook, hookRegistration) -> { //$NON-NLS-1$ //$NON-NLS-2$ + if (added) { + hook.added(listeners); + } else { + hook.removed(listeners); } }); } diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/weaving/WovenClassImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/weaving/WovenClassImpl.java index 77a8b4307..9326e92b9 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/weaving/WovenClassImpl.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/weaving/WovenClassImpl.java @@ -44,12 +44,10 @@ import org.osgi.framework.hooks.weaving.WovenClass; import org.osgi.framework.hooks.weaving.WovenClassListener; import org.osgi.framework.wiring.BundleWiring; -public final class WovenClassImpl implements WovenClass, HookContext { +public final class WovenClassImpl implements WovenClass, HookContext<WeavingHook> { private final static byte FLAG_HOOKCALLED = 0x01; private final static byte FLAG_HOOKSCOMPLETE = 0x02; private final static byte FLAG_WEAVINGCOMPLETE = 0x04; - final static String weavingHookName = WeavingHook.class.getName(); - final static String wovenClassListenerName = WovenClassListener.class.getName(); private final String className; private final BundleEntry entry; private final List<String> dynamicImports; @@ -169,35 +167,34 @@ public final class WovenClassImpl implements WovenClass, HookContext { } @Override - public void call(final Object hook, ServiceRegistration<?> hookRegistration) throws Exception { + public void call(final WeavingHook hook, ServiceRegistration<WeavingHook> hookRegistration) throws Exception { if (error != null) return; // do not call any other hooks once an error has occurred. - if (hook instanceof WeavingHook) { - if (skipRegistration(hookRegistration)) { - // Note we double check denied hooks here just - // in case another thread denied the hook since the first check - return; - } - if ((hookFlags & FLAG_HOOKCALLED) == 0) { - hookFlags |= FLAG_HOOKCALLED; - // only do this check on the first weaving hook call - if (!validBytes(validBytes)) { - validBytes = StorageUtil.getBytes(entry.getInputStream(), (int) entry.getSize(), 8 * 1024); - } - } - try { - ((WeavingHook) hook).weave(this); - } catch (WeavingException e) { - error = e; - errorHook = hookRegistration; - // do not deny the hook on weaving exceptions - } catch (Throwable t) { - error = t; // save the error to fail later - errorHook = hookRegistration; - // deny the registration - deniedHooks.put(hookRegistration, Boolean.TRUE); + + if (skipRegistration(hookRegistration)) { + // Note we double check denied hooks here just + // in case another thread denied the hook since the first check + return; + } + if ((hookFlags & FLAG_HOOKCALLED) == 0) { + hookFlags |= FLAG_HOOKCALLED; + // only do this check on the first weaving hook call + if (!validBytes(validBytes)) { + validBytes = StorageUtil.getBytes(entry.getInputStream(), (int) entry.getSize(), 8 * 1024); } } + try { + hook.weave(this); + } catch (WeavingException e) { + error = e; + errorHook = hookRegistration; + // do not deny the hook on weaving exceptions + } catch (Throwable t) { + error = t; // save the error to fail later + errorHook = hookRegistration; + // deny the registration + deniedHooks.put(hookRegistration, Boolean.TRUE); + } } @Override @@ -220,24 +217,22 @@ public final class WovenClassImpl implements WovenClass, HookContext { } private void notifyWovenClassListeners() { - final HookContext context = (hook, hookRegistration) -> { - if (!(hook instanceof WovenClassListener)) - return; + final HookContext<WovenClassListener> context = (hook, hookRegistration) -> { try { - ((WovenClassListener) hook).modified(WovenClassImpl.this); + hook.modified(WovenClassImpl.this); } catch (Exception e) { WovenClassImpl.this.container.getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, hookRegistration.getReference().getBundle(), e); } }; if (System.getSecurityManager() == null) - registry.notifyHooksPrivileged(wovenClassListenerName, "modified", context); //$NON-NLS-1$ + registry.notifyHooksPrivileged(WovenClassListener.class, "modified", context); //$NON-NLS-1$ else { try { AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { @Override public Void run() { - registry.notifyHooksPrivileged(wovenClassListenerName, "modified", context); //$NON-NLS-1$ + registry.notifyHooksPrivileged(WovenClassListener.class, "modified", context); //$NON-NLS-1$ return null; } }); @@ -254,13 +249,13 @@ public final class WovenClassImpl implements WovenClass, HookContext { boolean rejected = false; try { if (sm == null) { - registry.notifyHooksPrivileged(weavingHookName, "weave", this); //$NON-NLS-1$ + registry.notifyHooksPrivileged(WeavingHook.class, "weave", this); //$NON-NLS-1$ } else { try { AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { @Override public Void run() { - registry.notifyHooksPrivileged(weavingHookName, "weave", WovenClassImpl.this); //$NON-NLS-1$ + registry.notifyHooksPrivileged(WeavingHook.class, "weave", WovenClassImpl.this); //$NON-NLS-1$ return null; } }); |