/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Distributable under LGPL license. * See terms of license at gnu.org. */ package net.java.sip.communicator.service.systray; import net.java.sip.communicator.service.systray.event.*; import net.java.sip.communicator.util.*; import org.jitsi.service.configuration.*; import org.osgi.framework.*; import java.util.*; /** * Base implementation of {@link SystrayService}. Manages * PopupMessageHandlers and SystrayPopupMessageListeners. * * @author Nicolas Chamouard * @author Yana Stamcheva * @author Lyubomir Marinov * @author Symphorien Wanko * @author Pawel Domas */ public abstract class AbstractSystrayService implements SystrayService { /** * The logger */ private final Logger logger = Logger.getLogger(AbstractSystrayService.class); /** * OSGI bundle context */ private final BundleContext bundleContext; /** * The popup handler currently used to show popup messages */ private PopupMessageHandler activePopupHandler; /** * A set of usable PopupMessageHandler */ private final Hashtable popupHandlerSet = new Hashtable(); /** * List of listeners from early received calls to addPopupMessageListener. * Calls to addPopupMessageListener before the UIService is registered. */ private List earlyAddedListeners = null; /** * Creates new instance of AbstractSystrayService. * @param bundleContext OSGI bundle context that will be used by this * instance */ public AbstractSystrayService(BundleContext bundleContext) { this.bundleContext = bundleContext; } /** * Registers given PopupMessageHandler. * @param handler the PopupMessageHandler to be registered. */ protected void addPopupHandler(PopupMessageHandler handler) { popupHandlerSet.put(handler.getClass().getName(), handler); } /** * Removes given PopupMessageHandler. * @param handler the PopupMessageHandler to be removed. */ protected void removePopupHandler(PopupMessageHandler handler) { popupHandlerSet.remove(handler.getClass().getName()); } /** * Checks if given handlerClass is registered as a handler. * @param handlerClass the class name to be checked. * @return true if given handlerClass is already * registered as a handler. */ protected boolean containsHandler(String handlerClass) { return popupHandlerSet.contains(handlerClass); } /** * Returns active PopupMessageHandler. * @return active PopupMessageHandler. */ protected PopupMessageHandler getActivePopupHandler() { return activePopupHandler; } /** * Implements SystraService#showPopupMessage() * * @param popupMessage the message we will show */ public void showPopupMessage(PopupMessage popupMessage) { // since popup handler could be loaded and unloader on the fly, // we have to check if we currently have a valid one. if (activePopupHandler != null) activePopupHandler.showPopupMessage(popupMessage); } /** * Implements the SystrayService.addPopupMessageListener method. * If activePopupHandler is still not available record the listener * so we can add him later. * * @param listener the listener to add */ public void addPopupMessageListener(SystrayPopupMessageListener listener) { if (activePopupHandler != null) activePopupHandler.addPopupMessageListener(listener); else { if(earlyAddedListeners == null) earlyAddedListeners = new ArrayList(); earlyAddedListeners.add(listener); } } /** * Implements the SystrayService.removePopupMessageListener method. * * @param listener the listener to remove */ public void removePopupMessageListener(SystrayPopupMessageListener listener) { if (activePopupHandler != null) activePopupHandler.removePopupMessageListener(listener); } /** * Set the handler which will be used for popup message * @param newHandler the handler to set. providing a null handler is like * disabling popup. * @return the previously used popup handler */ public PopupMessageHandler setActivePopupMessageHandler( PopupMessageHandler newHandler) { PopupMessageHandler oldHandler = activePopupHandler; if (logger.isInfoEnabled()) { logger.info( "setting the following popup handler as active: " + newHandler); } activePopupHandler = newHandler; // if we have received calls to addPopupMessageListener before // the UIService is registered we should add those listeners if(earlyAddedListeners != null) { for(SystrayPopupMessageListener l : earlyAddedListeners) activePopupHandler.addPopupMessageListener(l); earlyAddedListeners.clear(); earlyAddedListeners = null; } return oldHandler; } /** * Get the handler currently used by this implementation to popup message * @return the current handler */ public PopupMessageHandler getActivePopupMessageHandler() { return activePopupHandler; } /** * Sets activePopupHandler to be the one with the highest preference index. */ public void selectBestPopupMessageHandler() { PopupMessageHandler preferredHandler = null; int highestPrefIndex = 0; if (!popupHandlerSet.isEmpty()) { Enumeration keys = popupHandlerSet.keys(); while (keys.hasMoreElements()) { String handlerName = keys.nextElement(); PopupMessageHandler h = popupHandlerSet.get(handlerName); if (h.getPreferenceIndex() > highestPrefIndex) { highestPrefIndex = h.getPreferenceIndex(); preferredHandler = h; } } setActivePopupMessageHandler(preferredHandler); } } /** * Initializes popup handler by searching registered services for class * PopupMessageHandler. */ protected void initHandlers() { // Listens for new popup handlers try { bundleContext.addServiceListener( new ServiceListenerImpl(), "(objectclass=" + PopupMessageHandler.class.getName() + ")"); } catch (Exception e) { logger.warn(e); } // now we look if some handler has been registered before we start // to listen Collection> handlerRefs = ServiceUtils.getServiceReferences( bundleContext, PopupMessageHandler.class); if (!handlerRefs.isEmpty()) { ConfigurationService config = ServiceUtils.getService( bundleContext, ConfigurationService.class); String configuredHandler = config.getString("systray.POPUP_HANDLER"); for (ServiceReference handlerRef : handlerRefs) { PopupMessageHandler handler = bundleContext.getService(handlerRef); String handlerName = handler.getClass().getName(); if (!containsHandler(handlerName)) { addPopupHandler(handler); if (logger.isInfoEnabled()) { logger.info( "added the following popup handler : " + handler); } if ((configuredHandler != null) && configuredHandler.equals( handler.getClass().getName())) { setActivePopupMessageHandler(handler); } } } if (configuredHandler == null) selectBestPopupMessageHandler(); } } /** An implementation of ServiceListener we will use */ private class ServiceListenerImpl implements ServiceListener { /** * implements ServiceListener.serviceChanged * @param serviceEvent */ public void serviceChanged(ServiceEvent serviceEvent) { try { Object service = bundleContext.getService( serviceEvent.getServiceReference()); // Event filters don't work on Android if(!(service instanceof PopupMessageHandler)) return; PopupMessageHandler handler = (PopupMessageHandler) bundleContext.getService( serviceEvent.getServiceReference()); if (serviceEvent.getType() == ServiceEvent.REGISTERED) { if (!containsHandler(handler.getClass().getName())) { if (logger.isInfoEnabled()) logger.info("adding the following popup handler : " + handler); addPopupHandler(handler); } else logger.warn("the following popup handler has not " + "been added since it is already known : " + handler); ConfigurationService cfg = ServiceUtils.getService( bundleContext, ConfigurationService.class); String configuredHandler = cfg.getString("systray.POPUP_HANDLER"); if ((configuredHandler == null) && ((getActivePopupHandler() == null) || (handler.getPreferenceIndex() > getActivePopupHandler().getPreferenceIndex()))) { // The user doesn't have a preferred handler set and new // handler with better preference index has arrived, // thus setting it as active. setActivePopupMessageHandler(handler); } if ((configuredHandler != null) && configuredHandler.equals( handler.getClass().getName())) { // The user has a preferred handler set and it just // became available, thus setting it as active setActivePopupMessageHandler(handler); } } else if (serviceEvent.getType() == ServiceEvent.UNREGISTERING) { if (logger.isInfoEnabled()) logger.info("removing the following popup handler : " + handler); removePopupHandler(handler); PopupMessageHandler activeHandler = getActivePopupHandler(); if (activeHandler == handler) { setActivePopupMessageHandler(null); // We just lost our default handler, so we replace it // with the one that has the highest preference index. selectBestPopupMessageHandler(); } } } catch (IllegalStateException e) { if (logger.isDebugEnabled()) logger.debug(e); } } } }