package net.sourceforge.javautil.groovy.proxy;
import java.lang.reflect.Proxy;
import groovy.lang.GroovyObject;
import javax.management.Attribute;
import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.IntrospectionException;
import javax.management.InvalidAttributeValueException;
import javax.management.MBeanException;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import org.codehaus.groovy.runtime.InvokerHelper;
import org.codehaus.groovy.runtime.metaclass.MissingPropertyExceptionNoStack;
import net.sourceforge.javautil.common.ReflectionUtil;
import net.sourceforge.javautil.common.exception.ThrowableManagerRegistry;
/**
* This will allow a target object name and MBeanServer to be specified allowing this to route
* the actual calls to the {@link MBeanServer} specification.
*
* @author elponderador
* @author $Author$
* @version $Id$
*/
public class GroovyObjectHandlerMBean extends GroovyObjectHandler {
/**
* @param objectName The object name of the mbean
* @param server The mbean server
* @return A groovy object that can be used for directly invoking the mbean
*/
public static GroovyObject create (String objectName, MBeanServer server) {
return (GroovyObject) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[] { GroovyObject.class }, new GroovyObjectHandlerMBean(objectName, server));
}
protected final ObjectName objectName;
protected final MBeanServer server;
public GroovyObjectHandlerMBean(String objectName, MBeanServer server) {
this.server = server;
try {
this.objectName = new ObjectName(objectName);
} catch (MalformedObjectNameException e) {
throw ThrowableManagerRegistry.caught(e);
} catch (NullPointerException e) {
throw ThrowableManagerRegistry.caught(e);
}
}
public Object getProperty(String propertyName) {
try {
if (!propertyName.substring(0, 1).equals(propertyName.substring(0, 1).toUpperCase())) {
propertyName = propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
}
return server.getAttribute(objectName, propertyName);
} catch (AttributeNotFoundException e) {
throw new MissingPropertyExceptionNoStack(propertyName, server.getClass());
} catch (InstanceNotFoundException e) {
throw ThrowableManagerRegistry.caught(e);
} catch (MBeanException e) {
throw ThrowableManagerRegistry.caught(e);
} catch (ReflectionException e) {
throw ThrowableManagerRegistry.caught(e);
}
}
public void setProperty(String propertyName, Object newValue) {
try {
if (!propertyName.substring(0, 1).equals(propertyName.substring(0, 1).toUpperCase())) {
propertyName = propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
}
server.setAttribute(objectName, new Attribute(propertyName, newValue));
} catch (InstanceNotFoundException e) {
throw ThrowableManagerRegistry.caught(e);
} catch (InvalidAttributeValueException e) {
throw ThrowableManagerRegistry.caught(e);
} catch (AttributeNotFoundException e) {
throw new MissingPropertyExceptionNoStack(propertyName, server.getClass());
} catch (ReflectionException e) {
throw ThrowableManagerRegistry.caught(e);
} catch (MBeanException e) {
throw ThrowableManagerRegistry.caught(e);
}
}
public Object invokeMethod(String name, Object args) {
Object[] aa = InvokerHelper.asArray(args);
try {
return server.invoke(objectName, name, aa, aa.length == 0 ? new String[0] : this.getMethodInfo(name, aa));
} catch (InstanceNotFoundException e) {
throw ThrowableManagerRegistry.caught(e);
} catch (ReflectionException e) {
throw ThrowableManagerRegistry.caught(e);
} catch (IntrospectionException e) {
throw ThrowableManagerRegistry.caught(e);
} catch (MBeanException e) {
throw ThrowableManagerRegistry.caught(e);
}
}
public String[] getMethodInfo (String name, Object[] args) throws InstanceNotFoundException, IntrospectionException, ReflectionException {
String[] ca = new String[args.length];
for (MBeanOperationInfo info : server.getMBeanInfo(objectName).getOperations()) {
if (info.getName().equals(name) && info.getSignature().length == ca.length) {
boolean match = true;
MBeanParameterInfo[] parameters = info.getSignature();
for (int a=0; a<ca.length; a++) {
MBeanParameterInfo parameter = parameters[a];
Class type = ReflectionUtil.getClass(parameter.getType());
ca[a] = type.getName();
if (args[a] == null) {
if (type.isPrimitive()) { match = false; break; }
} else {
if (!type.isInstance(args[a])) { match = false; break; }
}
}
if (match) return ca;
}
}
throw new UnsupportedOperationException("Could not find a matching operation for: " + name);
}
}