/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt 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.jboss.soa.esb.listeners.lifecycle;
import java.sql.Timestamp;
import java.util.Iterator;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.DynamicMBean;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.InvalidAttributeValueException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import org.apache.log4j.Logger;
import org.jboss.mx.util.MBeanServerLocator;
import org.jboss.soa.esb.helpers.ConfigTree;
import org.jboss.soa.esb.lifecycle.LifecycleResourceManager;
import org.jboss.soa.esb.listeners.ListenerTagNames;
/**
* LifecycleController is an MBean implementation that
*
* @author <a href="mailto:tcunning@redhat.com">tcunning@redhat.com</a>
*/
public class LifecycleController implements DynamicMBean {
private ManagedLifecycleAdapter m_lifecycle;
private String m_startTime;
private final ObjectName listObjectName ;
private final ClassLoader tccl ;
private static final Logger logger = Logger.getLogger(LifecycleController.class);
public static final String LIFECYCLESTATE_ATTRIB = "LifeCycleState";
public static final String STARTTIME_ATTRIB = "StartDate";
public static final String XML_ATTRIB = "ListenerXMLAsHtml";
public static final String START_ACTION = "start";
public static final String STOP_ACTION = "stop";
/**
* Constructor using lifecycle and config tree.
* @param f_lifecycle lifecycle
* @param f_configtree config tree
*/
public LifecycleController(ManagedLifecycleAdapter f_lifecycle) {
m_lifecycle = f_lifecycle;
m_startTime = "";
listObjectName = getObjectName() ;
tccl = Thread.currentThread().getContextClassLoader() ;
}
/**
* StartTime mutator.
* @param f_startTime start time
*/
protected void setStartTime(long f_startTime) {
Timestamp ts = new Timestamp(f_startTime);
m_startTime = ts.toString();
}
/**
*
*/
protected void unsetStartTime() {
m_startTime = "";
}
/**
* Lifecycle mutator.
* @param f_aml lifecycle
*/
public void setLifecycle(ManagedLifecycleAdapter f_aml) {
m_lifecycle = f_aml;
}
/**
* Gets the configtree XML as escaped HTML.
* @return configtree XML
*/
public String getListenerXMLAsHtml() {
return m_lifecycle.getConfig().toXml().replace("<", "<").replace(">", ">");
}
/**
* Calls start on the lifecycle.
*/
public void start() throws ManagedLifecycleException {
m_lifecycle.start();
}
/**
* Calls stop on the lifecycle.
*/
public void stop() throws ManagedLifecycleException {
m_lifecycle.stop();
}
/**
* Register this MBean with JBoss.
*/
protected void registerMBean() {
if (listObjectName == null) {
return ;
}
MBeanServer mbeanServer = null;
try {
mbeanServer = MBeanServerLocator.locateJBoss();
} catch (IllegalStateException ise) {
// If we can't find a JBoss MBeanServer, just return
// Needed for unit tests
return;
}
try {
mbeanServer.registerMBean(this, listObjectName);
} catch (InstanceAlreadyExistsException e) {
logger.error("", e);
} catch (MBeanRegistrationException e) {
logger.error("", e);
} catch (NotCompliantMBeanException e) {
logger.error("", e);
}
}
/**
* Unregister this MBean with JBoss.
*/
protected void unregisterMBean() {
if (listObjectName == null) {
return ;
}
MBeanServer mbeanServer = null;
try {
mbeanServer = MBeanServerLocator.locateJBoss();
} catch (IllegalStateException ise) {
// If we can't find a JBoss MBeanServer, just return
// Needed for unit tests
return;
}
try {
mbeanServer.unregisterMBean(listObjectName);
} catch (InstanceNotFoundException e) {
logger.error("", e);
} catch (MBeanRegistrationException e) {
logger.error("", e);
}
}
/**
* Gets the list of attributes. We return all Lifecycle attributes from the ConfigTree,
* and the start time, configtree XML, and the lifecycle state.
*/
public AttributeList getAttributes(String[] arg0) {
final ConfigTree config = m_lifecycle.getConfig() ;
AttributeList attributeList = new AttributeList();
Set<String> set = config.getAttributeNames();
String[] attribs = (String[])set.toArray(new String[set.size()]);
for (int i = 0; i < attribs.length; i++) {
Attribute at = new Attribute(attribs[i], config.getAttribute(attribs[i]));
attributeList.add(at);
}
// Add lifecycle state to the list of properties
Attribute lifecycleState = new Attribute(LIFECYCLESTATE_ATTRIB, m_lifecycle.getState().toString());
attributeList.add(lifecycleState);
Attribute startTimeAttrib = new Attribute(STARTTIME_ATTRIB, m_startTime);
attributeList.add(startTimeAttrib);
Attribute xmlAttrib = new Attribute(XML_ATTRIB, getListenerXMLAsHtml());
attributeList.add(xmlAttrib);
return attributeList;
}
/**
* Gets the attribute value.
*/
public synchronized String getAttribute(String name) throws AttributeNotFoundException {
String value = null;
if (name.equals(LIFECYCLESTATE_ATTRIB)) {
value = m_lifecycle.getState().toString();
} else if (name.equals(STARTTIME_ATTRIB)) {
value = m_startTime;
} else if (name.equals(XML_ATTRIB)) {
value = getListenerXMLAsHtml();
} else {
value = m_lifecycle.getConfig().getAttribute(name);
}
if (value != null)
return value;
else
throw new AttributeNotFoundException("No such property: " + name);
}
/**
* This creates the MBeanInfo object provided. We are returning generic
* text for the attribute descriptions (the word Property and the name of the
* attribute), all of the attributes are read-only, and we provide four
* invocation methods - start/stop/initialise/destroy on the Lifecycle.
*/
public MBeanInfo getMBeanInfo() {
SortedSet<String> names = new TreeSet<String>();
for (Object name : m_lifecycle.getConfig().getAttributeNames())
names.add((String) name);
names.add(LIFECYCLESTATE_ATTRIB);
names.add(STARTTIME_ATTRIB);
names.add(XML_ATTRIB);
MBeanAttributeInfo[] attrs = new MBeanAttributeInfo[names.size()];
Iterator<String> it = names.iterator();
for (int i = 0; i < attrs.length; i++) {
String name = it.next();
attrs[i] = new MBeanAttributeInfo(
name, "java.lang.String", "Property " + name, true, false, false);
}
MBeanOperationInfo[] opers = {
new MBeanOperationInfo(
START_ACTION, "Start the lifecycle",
null, "void", MBeanOperationInfo.ACTION),
new MBeanOperationInfo(
STOP_ACTION, "Stop the lifecycle",
null, "void", MBeanOperationInfo.ACTION),
};
return new MBeanInfo(
this.getClass().getName(), "Lifecycle Controller MBean",
attrs, null, opers, null); // notifications
}
/**
* Invoke calls the four operations provided by the LifecycleController -
* initialise, start, stop, destroy. If one of the operation methods fails,
* we throw the exception, and if an unknown operation is called, we throw
* an exception.
*/
public Object invoke(String method, Object[] arg1, String[] arg2) throws ReflectionException {
final ClassLoader current = Thread.currentThread().getContextClassLoader() ;
Thread.currentThread().setContextClassLoader(tccl) ;
try {
if (method.equalsIgnoreCase(START_ACTION)) {
try {
start();
} catch (ManagedLifecycleException e) {
logger.error("", e);
return "Error invoking " + method + ": " + e.toString();
}
return "Invoking the " + method + " on the lifecycle.";
} else if (method.equalsIgnoreCase(STOP_ACTION)) {
try {
stop();
} catch (ManagedLifecycleException e) {
logger.error("", e);
return "Error invoking " + method + ": " + e.toString();
}
return "Invoking the " + method + " on the lifecycle.";
} else {
throw new ReflectionException(new NoSuchMethodException(method));
}
} finally {
Thread.currentThread().setContextClassLoader(current) ;
}
}
/**
* This method is here to implement the DynamicMBean interface in full, but it is
* not used because all of the attributes provided are read-only.
*/
public void setAttribute(Attribute arg0) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {
}
/**
* This method is here to implement the DynamicMBean interface in full, but it is
* not used because all of the attributes provided are read-only.
*/
public AttributeList setAttributes(AttributeList arg0) {
return null;
}
protected ObjectName getObjectName()
{
ObjectName listObjectName = null;
try {
final ConfigTree config = m_lifecycle.getConfig() ;
String categoryName = config.getAttribute(ListenerTagNames.SERVICE_CATEGORY_NAME_TAG);
String serviceName = config.getAttribute(ListenerTagNames.SERVICE_NAME_TAG);
String targetCategoryName = config.getAttribute(ListenerTagNames.TARGET_SERVICE_CATEGORY_TAG);
String targetServiceName = config.getAttribute(ListenerTagNames.TARGET_SERVICE_NAME_TAG);
String listenerName = config.getAttribute(ListenerTagNames.NAME_TAG);
final LifecycleResourceManager lifecycleResourceManager = LifecycleResourceManager.getSingleton() ;
final String[] associatedDeployments = lifecycleResourceManager.getAssociatedDeployments() ;
final String deployment ;
if ((associatedDeployments != null) && (associatedDeployments.length == 1))
{
deployment = associatedDeployments[0] ;
}
else
{
deployment = lifecycleResourceManager.getIdentity() ;
}
StringBuffer objectName = new StringBuffer();
append(objectName, "deployment", deployment) ;
append(objectName, ListenerTagNames.SERVICE_CATEGORY_NAME_TAG, categoryName) ;
append(objectName, ListenerTagNames.SERVICE_NAME_TAG, serviceName);
append(objectName, ListenerTagNames.TARGET_SERVICE_CATEGORY_TAG, targetCategoryName);
append(objectName, ListenerTagNames.TARGET_SERVICE_NAME_TAG, targetServiceName);
if ("true".equals(config.getAttribute(ListenerTagNames.IS_GATEWAY_TAG))) {
append(objectName, "gateway-name", listenerName) ;
} else {
append(objectName, "listener-name", listenerName) ;
}
listObjectName = new ObjectName("jboss.esb:" + objectName.toString());
} catch (MalformedObjectNameException e1) {
logger.error("", e1);
} catch (NullPointerException e1) {
logger.error("", e1);
}
return listObjectName ;
}
private void append(final StringBuffer objectName, final String name, final String value)
{
if ((value != null) && (value.length() > 0)) {
if (objectName.length() > 0) {
objectName.append(",") ;
}
objectName.append(name).append("=").append(value) ;
}
}
}