/**
* Helios, OpenSource Monitoring
* Brought to you by the Helios Development Group
*
* Copyright 2007, Helios Development Group and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*
*/
package org.helios.apmrouter.jmx.mbeanserver.notifications;
import org.helios.apmrouter.jmx.mbeanserver.AgentMBeanServerConnectionFactory;
import org.helios.apmrouter.util.SimpleLogger;
import org.jboss.netty.channel.Channel;
import javax.management.*;
import java.net.SocketAddress;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* <p>Title: NotificationManager</p>
* <p>Description: Manages notification listeners passed by the remote JMX client</p>
* <p>Company: Helios Development Group LLC</p>
* @author Whitehead (nwhitehead AT heliosdev DOT org)
* <p><code>org.helios.apmrouter.jmx.mbeanserver.notifications.NotificationManager</code></p>
*/
public class NotificationManager {
/** A map of registered listeners keyed by request id */
protected final Map<Integer, NotificationListenerWrapper> listeners = new ConcurrentHashMap<Integer, NotificationListenerWrapper>();
/**
* <p>Title: NotificationListenerWrapper</p>
* <p>Description: A wrapper class to contain a registered listener and the MBeanServer it was registered in</p>
* <p>Company: Helios Development Group LLC</p>
* @author Whitehead (nwhitehead AT heliosdev DOT org)
* <p><code>org.helios.apmrouter.jmx.mbeanserver.notifications.NotificationManager.NotificationListenerWrapper</code></p>
*/
protected static class NotificationListenerWrapper {
/** The listener that was registered */
private final NotificationListener listener;
/** The MBeanServer the listener was registered with */
private final MBeanServer server;
/** The ObjectName that the listener was registered on */
private final ObjectName objectName;
/**
* Creates a new NotificationListenerWrapper
* @param listener The listener that was registered
* @param objectName The ObjectName that the listener was registered on
* @param server The MBeanServer the listener was registered with
*/
public NotificationListenerWrapper(NotificationListener listener, ObjectName objectName, MBeanServer server) {
this.listener = listener;
this.server = server;
this.objectName = objectName;
}
/**
* Unregisters the listener
* @return true if the listener was unregistered, false otherwise
*/
public boolean unregister() {
try {
server.removeNotificationListener(objectName, listener);
return true;
} catch (Exception ex) {
SimpleLogger.error("Failed to remove listener from MBean [", objectName, "]", ex);
return false;
}
}
}
/**
* Adds a listener to a registered MBean in the passed MBeanServer
* @param channel The channel to which emitted notifications should be written back to
* @param remoteAddress The remote address where the notification should be sent
* @param server The MBeanServer to register the listener with
* @param requestId The id of the listener registration request
* @param name The name of the MBean on which the listener should be added.
* @param filter The filter object. If filter is null, no filtering will be performed before handling notifications
* @param handback The context to be sent to the listener when a notification is emitted
*/
public void addNotificationListener(final Channel channel, final SocketAddress remoteAddress, final MBeanServer server, final int requestId, final ObjectName name, final NotificationFilter filter, final Object handback) {
try {
NotificationListener listener = new NotificationListener() {
@Override
public void handleNotification(Notification notification, Object handback) {
AgentMBeanServerConnectionFactory.writeNotification(channel, remoteAddress, requestId, notification, handback);
}
};
listeners.put(requestId, new NotificationListenerWrapper(listener, name, server));
server.addNotificationListener(name, listener, filter, handback);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
/**
* Removes a listener from a registered MBean from the passed MBeanServer
* @param requestId The requestId of the request that registered the listener to be removed.
* @return true if the listener was found and unregistered, false otherwise
*/
public boolean removeNotificationListener(int requestId) {
NotificationListenerWrapper wrapper = listeners.remove(requestId);
if(wrapper!=null) {
return wrapper.unregister();
}
return false;
}
}