/*
* Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package com.sun.jmx.mbeanserver;
import static com.sun.jmx.mbeanserver.Util.*;
import java.lang.reflect.Method;
import java.util.Map;
import javax.management.Attribute;
import javax.management.MBeanServerConnection;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
/**
Helper class for an {@link InvocationHandler} that forwards methods from an
MXBean interface to a named
MXBean in an MBean Server and handles translation between the
arbitrary Java types in the interface and the Open Types used
by the MXBean.
@since 1.6
*/
public class MXBeanProxy {
public MXBeanProxy(Class> mxbeanInterface) {
if (mxbeanInterface == null)
throw new IllegalArgumentException("Null parameter");
final MBeanAnalyzer analyzer;
try {
analyzer =
MXBeanIntrospector.getInstance().getAnalyzer(mxbeanInterface);
} catch (NotCompliantMBeanException e) {
throw new IllegalArgumentException(e);
}
analyzer.visit(new Visitor());
}
private class Visitor
implements MBeanAnalyzer.MBeanVisitor {
public void visitAttribute(String attributeName,
ConvertingMethod getter,
ConvertingMethod setter) {
if (getter != null) {
getter.checkCallToOpen();
Method getterMethod = getter.getMethod();
handlerMap.put(getterMethod,
new GetHandler(attributeName, getter));
}
if (setter != null) {
// return type is void, no need for checkCallToOpen
Method setterMethod = setter.getMethod();
handlerMap.put(setterMethod,
new SetHandler(attributeName, setter));
}
}
public void visitOperation(String operationName,
ConvertingMethod operation) {
operation.checkCallToOpen();
Method operationMethod = operation.getMethod();
String[] sig = operation.getOpenSignature();
handlerMap.put(operationMethod,
new InvokeHandler(operationName, sig, operation));
}
}
private static abstract class Handler {
Handler(String name, ConvertingMethod cm) {
this.name = name;
this.convertingMethod = cm;
}
String getName() {
return name;
}
ConvertingMethod getConvertingMethod() {
return convertingMethod;
}
abstract Object invoke(MBeanServerConnection mbsc,
ObjectName name, Object[] args) throws Exception;
private final String name;
private final ConvertingMethod convertingMethod;
}
private static class GetHandler extends Handler {
GetHandler(String attributeName, ConvertingMethod cm) {
super(attributeName, cm);
}
@Override
Object invoke(MBeanServerConnection mbsc, ObjectName name, Object[] args)
throws Exception {
assert(args == null || args.length == 0);
return mbsc.getAttribute(name, getName());
}
}
private static class SetHandler extends Handler {
SetHandler(String attributeName, ConvertingMethod cm) {
super(attributeName, cm);
}
@Override
Object invoke(MBeanServerConnection mbsc, ObjectName name, Object[] args)
throws Exception {
assert(args.length == 1);
Attribute attr = new Attribute(getName(), args[0]);
mbsc.setAttribute(name, attr);
return null;
}
}
private static class InvokeHandler extends Handler {
InvokeHandler(String operationName, String[] signature,
ConvertingMethod cm) {
super(operationName, cm);
this.signature = signature;
}
Object invoke(MBeanServerConnection mbsc, ObjectName name, Object[] args)
throws Exception {
return mbsc.invoke(name, getName(), args, signature);
}
private final String[] signature;
}
public Object invoke(MBeanServerConnection mbsc, ObjectName name,
Method method, Object[] args)
throws Throwable {
Handler handler = handlerMap.get(method);
ConvertingMethod cm = handler.getConvertingMethod();
MXBeanLookup lookup = MXBeanLookup.lookupFor(mbsc);
MXBeanLookup oldLookup = MXBeanLookup.getLookup();
try {
MXBeanLookup.setLookup(lookup);
Object[] openArgs = cm.toOpenParameters(lookup, args);
Object result = handler.invoke(mbsc, name, openArgs);
return cm.fromOpenReturnValue(lookup, result);
} finally {
MXBeanLookup.setLookup(oldLookup);
}
}
private final Map handlerMap = newMap();
}