/*
* IronJacamar, a Java EE Connector Architecture implementation
* Copyright 2016, Red Hat Inc, 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 Eclipse Public License 1.0 as
* published by the Free Software Foundation.
*
* 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 Eclipse
* Public License for more details.
*
* You should have received a copy of the Eclipse 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.ironjacamar.web.console;
import java.beans.IntrospectionException;
import java.beans.PropertyEditor;
import java.beans.PropertyEditorManager;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeMap;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.JMException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import org.jboss.logging.Logger;
import org.jboss.util.Classes;
import org.jboss.util.propertyeditor.PropertyEditors;
/**
* Utility methods related to the MBeanServer interface
* @author <a href="mailto:sstark@redhat.com">Scott Stark</a>
* @author <a href="mailto:dimitris@ironjacamar.org">Dimitris Andreadis</a>
* @author <a href="mailto:jesper.pedersen@ironjacamar.org">Jesper Pedersen</a>
*/
public class Server
{
private static Logger log = Logger.getLogger(Server.class);
private static boolean trace = log.isTraceEnabled();
private static MBeanServer mbeanServer = null;
/**
* Get the platform MBeanServer instance
* @return The instance
*/
public static MBeanServer getMBeanServer()
{
return ManagementFactory.getPlatformMBeanServer();
}
/**
* Get the MBeanServer instance
* @param domain The domain
* @return The instance
*/
public static MBeanServer getMBeanServer(String domain)
{
try
{
ArrayList<MBeanServer> l = MBeanServerFactory.findMBeanServer(null);
if (l != null)
{
for (MBeanServer ms : l)
{
String[] domains = ms.getDomains();
if (domains != null)
{
for (String d : domains)
{
if (domain.equals(d))
{
return ms;
}
}
}
}
}
}
catch (SecurityException se)
{
// Ignore
}
return null;
}
/**
* Get the domain data
* @return The data iterator
* @exception JMException Thrown if an error occurs
*/
public static Iterator getDomainData() throws JMException
{
MBeanServer server = getMBeanServer();
TreeMap<String, DomainData> domainData = new TreeMap<String, DomainData>();
if (server != null)
{
Set objectNames = server.queryNames(null, null);
Iterator objectNamesIter = objectNames.iterator();
while (objectNamesIter.hasNext())
{
ObjectName name = (ObjectName)objectNamesIter.next();
MBeanInfo info = server.getMBeanInfo(name);
String domainName = name.getDomain();
MBeanData mbeanData = new MBeanData(name, info);
DomainData data = domainData.get(domainName);
if (data == null)
{
data = new DomainData(domainName);
domainData.put(domainName, data);
}
data.addData(mbeanData);
}
}
return domainData.values().iterator();
}
/**
* Get MBean data
* @param name The bean name
* @return The data
* @exception JMException Thrown if an error occurs
*/
public static MBeanData getMBeanData(String name) throws JMException
{
MBeanServer server = getMBeanServer();
ObjectName objName = new ObjectName(name);
MBeanInfo info = server.getMBeanInfo(objName);
return new MBeanData(objName, info);
}
/**
* Get MBean attribute object
* @param name The bean name
* @param attrName The attribute name
* @return The data
* @exception JMException Thrown if an error occurs
*/
public static Object getMBeanAttributeObject(String name, String attrName) throws JMException
{
MBeanServer server = getMBeanServer();
ObjectName objName = new ObjectName(name);
return server.getAttribute(objName, attrName);
}
/**
* Get MBean attribute
* @param name The bean name
* @param attrName The attribute name
* @return The data
* @exception JMException Thrown if an error occurs
*/
public static String getMBeanAttribute(String name, String attrName) throws JMException
{
MBeanServer server = getMBeanServer();
ObjectName objName = new ObjectName(name);
String value = null;
try
{
Object attr = server.getAttribute(objName, attrName);
if (attr != null)
value = attr.toString();
}
catch (JMException e)
{
value = e.getMessage();
}
return value;
}
/**
* Get MBean attribute result info
* @param name The bean name
* @param attrInfo The attribute information
* @return The data
* @exception JMException Thrown if an error occurs
*/
public static AttrResultInfo getMBeanAttributeResultInfo(String name, MBeanAttributeInfo attrInfo)
throws JMException
{
ClassLoader loader = SecurityActions.getThreadContextClassLoader();
MBeanServer server = getMBeanServer();
ObjectName objName = new ObjectName(name);
String attrName = attrInfo.getName();
String attrType = attrInfo.getType();
Object value = null;
Throwable throwable = null;
if (attrInfo.isReadable())
{
try
{
value = server.getAttribute(objName, attrName);
}
catch (Throwable t)
{
throwable = t;
}
}
Class typeClass = null;
try
{
typeClass = Classes.getPrimitiveTypeForName(attrType);
if (typeClass == null)
typeClass = loader.loadClass(attrType);
}
catch (ClassNotFoundException cnfe)
{
// Ignore
}
PropertyEditor editor = null;
if (typeClass != null)
editor = PropertyEditorManager.findEditor(typeClass);
return new AttrResultInfo(attrName, editor, value, throwable);
}
/**
* Set MBean attributes
* @param name The bean name
* @param attributes The attributes
* @return The updated attribute list
* @exception JMException Thrown if an error occurs
*/
public static AttributeList setAttributes(String name, HashMap attributes) throws JMException
{
MBeanServer server = getMBeanServer();
ObjectName objName = new ObjectName(name);
MBeanInfo info = server.getMBeanInfo(objName);
MBeanAttributeInfo[] attributesInfo = info.getAttributes();
AttributeList newAttributes = new AttributeList();
for (int a = 0; a < attributesInfo.length; a++)
{
MBeanAttributeInfo attrInfo = attributesInfo[a];
String attrName = attrInfo.getName();
if (!attributes.containsKey(attrName))
continue;
String value = (String) attributes.get(attrName);
if (value.equals("null") && server.getAttribute(objName, attrName) == null)
{
if (trace)
log.trace("ignoring 'null' for " + attrName);
continue;
}
String attrType = attrInfo.getType();
Attribute attr = null;
try
{
Object realValue = PropertyEditors.convertValue(value, attrType);
attr = new Attribute(attrName, realValue);
}
catch (ClassNotFoundException e)
{
if (trace)
log.trace("Failed to load class for attribute: " + attrType, e);
throw new ReflectionException(e, "Failed to load class for attribute: " + attrType);
}
catch (IntrospectionException e)
{
if (trace)
log.trace("Skipped setting attribute: " + attrName +
", cannot find PropertyEditor for type: " + attrType);
continue;
}
server.setAttribute(objName, attr);
newAttributes.add(attr);
}
return newAttributes;
}
/**
* Invoke an operation
* @param name The bean name
* @param index The method index
* @param args The arguments
* @return The result
* @exception JMException Thrown if an error occurs
*/
public static OpResultInfo invokeOp(String name, int index, String[] args) throws JMException
{
MBeanServer server = getMBeanServer();
ObjectName objName = new ObjectName(name);
MBeanInfo info = server.getMBeanInfo(objName);
MBeanOperationInfo[] opInfo = info.getOperations();
MBeanOperationInfo op = opInfo[index];
MBeanParameterInfo[] paramInfo = op.getSignature();
String[] argTypes = new String[paramInfo.length];
for (int p = 0; p < paramInfo.length; p++)
argTypes[p] = paramInfo[p].getType();
return invokeOpByName(name, op.getName(), argTypes, args);
}
/**
* Invoke an operation by name
* @param name The bean name
* @param opName The operation name
* @param argTypes The argument types
* @param args The arguments
* @return The result
* @exception JMException Thrown if an error occurs
*/
public static OpResultInfo invokeOpByName(String name, String opName, String[] argTypes, String[] args)
throws JMException
{
MBeanServer server = getMBeanServer();
ObjectName objName = new ObjectName(name);
int length = argTypes != null ? argTypes.length : 0;
Object[] typedArgs = new Object[length];
for (int p = 0; p < typedArgs.length; p++)
{
String arg = args[p];
try
{
Object argValue = PropertyEditors.convertValue(arg, argTypes[p]);
typedArgs[p] = argValue;
}
catch (ClassNotFoundException e)
{
if (trace)
log.trace("Failed to load class for arg" + p, e);
throw new ReflectionException(e, "Failed to load class for arg" + p);
}
catch (java.beans.IntrospectionException e)
{
// If the type is not java.lang.Object throw an exception
if (!argTypes[p].equals("java.lang.Object"))
throw new javax.management.IntrospectionException("Failed to find PropertyEditor for type: " +
argTypes[p]);
// Just use the String arg
typedArgs[p] = arg;
continue;
}
}
Object opReturn = server.invoke(objName, opName, typedArgs, argTypes);
return new OpResultInfo(opName, argTypes, args, opReturn);
}
}