/*
* RHQ Management Platform
* Copyright (C) 2005-2008 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.rhq.enterprise.communications.command.server.discovery;
import javax.management.InstanceNotFoundException;
import javax.management.ListenerNotFoundException;
import javax.management.MalformedObjectNameException;
import javax.management.Notification;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import org.jboss.remoting.network.NetworkNotification;
import org.rhq.enterprise.communications.ServiceContainer;
import org.rhq.enterprise.communications.command.server.CommandMBean;
import org.rhq.enterprise.communications.i18n.CommI18NResourceKeys;
/**
* Provides a mechanism to integrate with JBoss/Remoting's Network Registry in order to detect new servers coming on and
* offline.
*
* @author John Mazzitelli
*/
public abstract class AutoDiscovery extends CommandMBean implements AutoDiscoveryMBean, NotificationListener {
/**
* this is the default name of the Network Registery MBean
*/
private static final String DEFAULT_NETWORK_REGISTRY_NAME = ServiceContainer.OBJECTNAME_NETWORK_REGISTRY.toString();
/**
* The name of the Network Registry MBean, as an <code>ObjectName</code>.
*/
private ObjectName m_networkRegistryName = null;
/**
* When <code>true</code>, indicates this object is listening to the Network Registry.
*/
private boolean m_listening = false;
/**
* @see AutoDiscoveryMBean#getNetworkRegistryName()
*/
public String getNetworkRegistryName() {
return m_networkRegistryName.toString();
}
/**
* @see AutoDiscoveryMBean#setNetworkRegistryName(String)
*/
public void setNetworkRegistryName(String name) {
// if there is already a name defined, make sure we are no longer going to listen to that Network Registry
if (m_networkRegistryName != null) {
try {
unregisterNotificationListener();
} catch (AutoDiscoveryException ade) {
getLog().warn(ade, CommI18NResourceKeys.FAILED_TO_STOP_LISTENING);
}
}
// create the new Network Registry name
try {
m_networkRegistryName = new ObjectName(name);
} catch (MalformedObjectNameException moe) {
throw new IllegalArgumentException(getLog().getMsgString(CommI18NResourceKeys.INVALID_REGISTRY_NAME, moe));
}
getLog().info(CommI18NResourceKeys.REGISTRY_NAME, name);
// now start listening to that new Network Registry
try {
registerNotificationListener();
} catch (AutoDiscoveryException ade) {
getLog().warn(ade, CommI18NResourceKeys.FAILED_TO_START_LISTENING, name);
}
return;
}
/**
* Returns the Network Registry Name as an <code>ObjectName</code>.
*
* @return the MBean name of the Network Registry
*
* @see AutoDiscoveryMBean#getNetworkRegistryName()
*/
public ObjectName getNetworkRegistryObjectName() {
return m_networkRegistryName;
}
/**
* Receives notifications from the Network Registry indicating that servers are either coming on or offline.
*
* @see NotificationListener#handleNotification(javax.management.Notification, java.lang.Object)
*/
public void handleNotification(Notification notification, Object handback) {
// check to see if it is a network registry notification
if (notification instanceof NetworkNotification) {
NetworkNotification networkNotification = (NetworkNotification) notification;
String notifType = networkNotification.getType();
// check to see if notification is for new servers being added
if (NetworkNotification.SERVER_ADDED.equals(notifType)) {
discoveredNewServers(networkNotification);
} else if (NetworkNotification.SERVER_REMOVED.equals(notifType)) {
discoveredRemovedServers(networkNotification);
} else if (NetworkNotification.SERVER_UPDATED.equals(notifType)) {
discoveredUpdatedServers(networkNotification);
} else if (NetworkNotification.DOMAIN_CHANGED.equals(notifType)) {
discoveredChangedDomain(networkNotification);
} else {
getLog().warn(CommI18NResourceKeys.UNKNOWN_NOTIF_TYPE, notifType);
}
} else {
getLog().warn(CommI18NResourceKeys.UNKNOWN_NOTIF, notification.getClass());
}
return;
}
/**
* Unregisters this object as a notification listener on the Network Registry.
*/
public void stopService() {
try {
unregisterNotificationListener();
} catch (Exception e) {
// ignore this - we don't care, we are shutting down anyway
}
return;
}
/**
* Registers this object as a notification listener to the Network Registry. After this call, this object will start
* getting notifications of servers coming on and offline as detected by the Network Registry.
*
* @throws AutoDiscoveryException if failed to start listening to the Network Registry
*/
private void registerNotificationListener() throws AutoDiscoveryException {
if (!m_listening) {
try {
if (m_networkRegistryName == null) {
setNetworkRegistryName(DEFAULT_NETWORK_REGISTRY_NAME);
}
getMBeanServer().addNotificationListener(m_networkRegistryName, this, null, null);
m_listening = true;
} catch (Exception e) {
throw new AutoDiscoveryException(getLog().getMsgString(CommI18NResourceKeys.FAILED_TO_START_LISTENING,
m_networkRegistryName), e);
}
}
return;
}
/**
* Removes this object as a notification listener from the Network Registry. After this call, this object will no
* longer get notifications from the Network Registry. Note that if this object is not yet listening to the Network
* Registry, this method simply returns and does nothing.
*
* @throws AutoDiscoveryException if failed to unregister
*/
private void unregisterNotificationListener() throws AutoDiscoveryException {
if (m_listening) {
try {
getMBeanServer().removeNotificationListener(m_networkRegistryName, this);
} catch (ListenerNotFoundException e) {
// ignore this - looks like we weren't registered anyway, so we got what we want - we aren't registered
} catch (InstanceNotFoundException e) {
// ignore this - looks like the Network Registry has already gone away
} catch (Exception e) {
throw new AutoDiscoveryException(getLog().getMsgString(CommI18NResourceKeys.UNREGISTER_FAILURE,
m_networkRegistryName), e);
}
m_listening = false;
}
return;
}
/**
* Processes a Network Registry notification that indicates new servers have come online.
*
* @param networkNotification the notification that was received from the Network Registry
*/
public abstract void discoveredNewServers(NetworkNotification networkNotification);
/**
* Processes a Network Registry notification that indicates servers have gone offline.
*
* @param networkNotification the notification that was received from the Network Registry
*/
public abstract void discoveredRemovedServers(NetworkNotification networkNotification);
/**
* Processes a Network Registry notification that indicates servers have been updated.
*
* @param networkNotification the notification that was received from the Network Registry
*/
public abstract void discoveredUpdatedServers(NetworkNotification networkNotification);
/**
* Processes a Network Registry notification that indicates the domain has changed.
*
* @param networkNotification the notification that was received from the Network Registry
*/
public abstract void discoveredChangedDomain(NetworkNotification networkNotification);
}