/****************************************************************************** * Copyright (c) 2006, 2010 VMware Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Apache License v2.0 which accompanies this distribution. * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0 * is available at http://www.opensource.org/licenses/apache2.0.php. * You may elect to redistribute this code under either of these licenses. * * Contributors: * VMware Inc. *****************************************************************************/ package org.eclipse.gemini.blueprint.extender.internal.activator; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.util.Map; import java.util.WeakHashMap; import org.osgi.framework.BundleContext; import org.osgi.util.tracker.ServiceTracker; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.core.GenericTypeResolver; import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEvent; import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextListener; /** * Listener interface that delegates to a list of listener. This is useful in OSGi environments when dealing with * dynamic collections which can be updated during iteration. * * @author Costin Leau * */ @SuppressWarnings("unchecked") class ListListenerAdapter implements OsgiBundleApplicationContextListener<OsgiBundleApplicationContextEvent>, InitializingBean, DisposableBean { private final ServiceTracker tracker; private final Map<Class<? extends OsgiBundleApplicationContextListener>, Class<? extends OsgiBundleApplicationContextEvent>> eventCache = new WeakHashMap<Class<? extends OsgiBundleApplicationContextListener>, Class<? extends OsgiBundleApplicationContextEvent>>(); /** * Constructs a new <code>ListListenerAdapter</code> instance. * * @param listeners */ public ListListenerAdapter(BundleContext bundleContext) { this.tracker = new ServiceTracker(bundleContext, OsgiBundleApplicationContextListener.class.getName(), null); } public void afterPropertiesSet() { this.tracker.open(); } public void destroy() { this.tracker.close(); eventCache.clear(); } public void onOsgiApplicationEvent(OsgiBundleApplicationContextEvent event) { Object[] listeners = tracker.getServices(); if (listeners != null) { synchronized (eventCache) { for (Object listnr : listeners) { OsgiBundleApplicationContextListener listener = (OsgiBundleApplicationContextListener) listnr; Class<? extends OsgiBundleApplicationContextListener> listenerClass = listener.getClass(); Class<? extends OsgiBundleApplicationContextEvent> eventType = eventCache.get(listenerClass); if (eventType == null) { Class<?> evtType = GenericTypeResolver.resolveTypeArgument(listenerClass, OsgiBundleApplicationContextListener.class); if (evtType == null) { evtType = OsgiBundleApplicationContextEvent.class; } if (evtType != null && evtType.isAssignableFrom(OsgiBundleApplicationContextEvent.class)) { eventType = (Class<? extends OsgiBundleApplicationContextEvent>) evtType; } else { eventType = OsgiBundleApplicationContextEvent.class; } eventCache.put(listenerClass, eventType); } if (eventType.isInstance(event)) { listener.onOsgiApplicationEvent(event); } } } } } }