/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Copyright @ 2015 Atlassian Pty Ltd
*
* Licensed 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 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);
}
/**
* Stub method that does nothing.
* @param count ignored
*/
@Override
public void setNotificationCount(int count)
{
}
/**
* 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);
}
}
}
}