*
* @param notification The notification to send
*/
public void sendNotification(Notification notification)
{
Logger logger = getLogger();
boolean trace = logger.isEnabledFor(Logger.TRACE);
boolean info = logger.isEnabledFor(Logger.INFO);
HashMap listeners = null;
synchronized (this)
{
// Clone the listeners, so we can notify without holding any lock
// It is a shallow copy, below we will clone the pairs as well
// I don't care if in the middle someone else adds or remove other pairs
listeners = (HashMap)m_listeners.clone();
}
// Loop over all listeners
Iterator i = listeners.keySet().iterator();
if (i.hasNext() && trace) logger.trace("Sending notifications from " + this);
while (i.hasNext())
{
NotificationListener listener = (NotificationListener)i.next();
if (trace) logger.trace("\tListener is: " + listener);
// Clone again the pairs for this listener.
// I freezed the listeners with the first clone, if someone removes a pair
// in the middle of notifications I don't care: here I clone the actual pairs
ArrayList pairs = null;
synchronized (this)
{
pairs = (ArrayList)listeners.get(listener);
pairs = (ArrayList)pairs.clone();
}
if (trace) logger.trace("\tFilters - Handback for this listener: " + pairs);
// Loop over the same listener that registered many times with different filter / handbacks
for (int j = 0; j < pairs.size(); ++j)
{
FilterHandbackPair pair = (FilterHandbackPair)pairs.get(j);
NotificationFilter filter = pair.filter;
Object handback = pair.handback;
// Denormalize filter and handback if necessary
if (filter == NULL_FILTER) filter = null;
if (handback == NULL_HANDBACK) handback = null;
boolean enabled = false;
try
{
enabled = filter == null || filter.isNotificationEnabled(notification);
}
catch (Throwable x)
{
if (info) logger.info("Throwable caught from isNotificationEnabled", x);
// And go on
}
if (trace) logger.trace("\t\tFilter is: " + filter + ", enabled: " + enabled);
if (enabled)
{
if (trace)
{
logger.debug("\t\tHandback is: " + handback);
logger.debug("\t\tSending notification " + notification);
}
try
{
handleNotification(listener, notification, handback);
}
catch (Throwable x)
{
if (info) logger.info("Throwable caught from handleNotification", x);
// And go on with next listener
}
}
}
}