mbeanclientinterceptor.java
来自「spring framework 2.5.4源代码」· Java 代码 · 共 514 行 · 第 1/2 页
JAVA
514 行
this.allowedOperations.put(new MethodCacheKey(opInfo.getName(), paramTypes), opInfo);
}
}
catch (ClassNotFoundException ex) {
throw new MBeanInfoRetrievalException("Unable to locate class specified in method signature", ex);
}
catch (IntrospectionException ex) {
throw new MBeanInfoRetrievalException("Unable to obtain MBean info for bean [" + this.objectName + "]", ex);
}
catch (InstanceNotFoundException ex) {
// if we are this far this shouldn't happen, but...
throw new MBeanInfoRetrievalException("Unable to obtain MBean info for bean [" + this.objectName +
"]: it is likely that this bean was unregistered during the proxy creation process",
ex);
}
catch (ReflectionException ex) {
throw new MBeanInfoRetrievalException("Unable to read MBean info for bean [ " + this.objectName + "]", ex);
}
catch (IOException ex) {
throw new MBeanInfoRetrievalException(
"An IOException occurred when communicating with the MBeanServer. " +
"It is likely that you are communicating with a remote MBeanServer. " +
"Check the inner exception for exact details.", ex);
}
}
/**
* Return whether this client interceptor has already been prepared,
* i.e. has already looked up the server and cached all metadata.
*/
protected boolean isPrepared() {
synchronized (this.preparationMonitor) {
return (this.invocationHandler != null || this.allowedAttributes != null);
}
}
/**
* Route the invocation to the configured managed resource. Correctly routes JavaBean property
* access to <code>MBeanServerConnection.get/setAttribute</code> and method invocation to
* <code>MBeanServerConnection.invoke</code>. Any attempt to invoke a method that does not
* correspond to an attribute or operation defined in the management interface of the managed
* resource results in an <code>InvalidInvocationException</code>.
* @param invocation the <code>MethodInvocation</code> to re-route.
* @return the value returned as a result of the re-routed invocation.
* @throws InvocationFailureException if the invocation does not match an attribute or
* operation on the management interface of the resource.
* @throws Throwable typically as the result of an error during invocation
*/
public Object invoke(MethodInvocation invocation) throws Throwable {
// Lazily connect to MBeanServer if necessary.
synchronized (this.preparationMonitor) {
if (!isPrepared()) {
prepare();
}
}
Method method = invocation.getMethod();
try {
Object result = null;
if (this.invocationHandler != null) {
result = this.invocationHandler.invoke(invocation.getThis(), method, invocation.getArguments());
}
else {
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method);
if (pd != null) {
result = invokeAttribute(pd, invocation);
}
else {
result = invokeOperation(method, invocation.getArguments());
}
}
return convertResultValueIfNecessary(result, method.getReturnType());
}
catch (MBeanException ex) {
throw ex.getTargetException();
}
catch (RuntimeMBeanException ex) {
throw ex.getTargetException();
}
catch (RuntimeErrorException ex) {
throw ex.getTargetError();
}
catch (RuntimeOperationsException ex) {
// This one is only thrown by the JMX 1.2 RI, not by the JDK 1.5 JMX code.
RuntimeException rex = ex.getTargetException();
if (rex instanceof RuntimeMBeanException) {
throw ((RuntimeMBeanException) rex).getTargetException();
}
else if (rex instanceof RuntimeErrorException) {
throw ((RuntimeErrorException) rex).getTargetError();
}
else {
throw rex;
}
}
catch (OperationsException ex) {
if (ReflectionUtils.declaresException(method, ex.getClass())) {
throw ex;
}
else {
throw new InvalidInvocationException(ex.getMessage());
}
}
catch (JMException ex) {
if (ReflectionUtils.declaresException(method, ex.getClass())) {
throw ex;
}
else {
throw new InvocationFailureException("JMX access failed", ex);
}
}
catch (IOException ex) {
if (ReflectionUtils.declaresException(method, ex.getClass())) {
throw ex;
}
else {
throw new InvocationFailureException("I/O failure during JMX access", ex);
}
}
}
private Object invokeAttribute(PropertyDescriptor pd, MethodInvocation invocation)
throws JMException, IOException {
String attributeName = JmxUtils.getAttributeName(pd, this.useStrictCasing);
MBeanAttributeInfo inf = (MBeanAttributeInfo) this.allowedAttributes.get(attributeName);
// If no attribute is returned, we know that it is not defined in the
// management interface.
if (inf == null) {
throw new InvalidInvocationException(
"Attribute '" + pd.getName() + "' is not exposed on the management interface");
}
if (invocation.getMethod().equals(pd.getReadMethod())) {
if (inf.isReadable()) {
return this.server.getAttribute(this.objectName, attributeName);
}
else {
throw new InvalidInvocationException("Attribute '" + attributeName + "' is not readable");
}
}
else if (invocation.getMethod().equals(pd.getWriteMethod())) {
if (inf.isWritable()) {
this.server.setAttribute(this.objectName, new Attribute(attributeName, invocation.getArguments()[0]));
return null;
}
else {
throw new InvalidInvocationException("Attribute '" + attributeName + "' is not writable");
}
}
else {
throw new IllegalStateException(
"Method [" + invocation.getMethod() + "] is neither a bean property getter nor a setter");
}
}
/**
* Routes a method invocation (not a property get/set) to the corresponding
* operation on the managed resource.
* @param method the method corresponding to operation on the managed resource.
* @param args the invocation arguments
* @return the value returned by the method invocation.
*/
private Object invokeOperation(Method method, Object[] args) throws JMException, IOException {
MethodCacheKey key = new MethodCacheKey(method.getName(), method.getParameterTypes());
MBeanOperationInfo info = (MBeanOperationInfo) this.allowedOperations.get(key);
if (info == null) {
throw new InvalidInvocationException("Operation '" + method.getName() +
"' is not exposed on the management interface");
}
String[] signature = null;
synchronized (this.signatureCache) {
signature = (String[]) this.signatureCache.get(method);
if (signature == null) {
signature = JmxUtils.getMethodSignature(method);
this.signatureCache.put(method, signature);
}
}
return this.server.invoke(this.objectName, method.getName(), args, signature);
}
/**
* Convert the given result object (from attribute access or operation invocation)
* to the specified target class for returning from the proxy method.
* @param result the result object as returned by the <code>MBeanServer</code>
* @param targetClass the result type of the proxy method that's been invoked
* @return the converted result object, or the passed-in object if no conversion
* is necessary
*/
protected Object convertResultValueIfNecessary(Object result, Class targetClass) {
try {
if (result == null) {
return null;
}
if (ClassUtils.isAssignableValue(targetClass, result)) {
return result;
}
if (result instanceof CompositeData) {
Method fromMethod = targetClass.getMethod("from", new Class[] {CompositeData.class});
return ReflectionUtils.invokeMethod(fromMethod, null, new Object[] {result});
}
else if (result instanceof TabularData) {
Method fromMethod = targetClass.getMethod("from", new Class[] {TabularData.class});
return ReflectionUtils.invokeMethod(fromMethod, null, new Object[] {result});
}
else {
throw new InvocationFailureException(
"Incompatible result value [" + result + "] for target type [" + targetClass.getName() + "]");
}
}
catch (NoSuchMethodException ex) {
throw new InvocationFailureException(
"Could not obtain 'find(CompositeData)' / 'find(TabularData)' method on target type [" +
targetClass.getName() + "] for conversion of MXBean data structure [" + result + "]");
}
}
public void destroy() {
this.connector.close();
}
/**
* Simple wrapper class around a method name and its signature.
* Used as the key when caching methods.
*/
private static class MethodCacheKey {
private final String name;
private final Class[] parameterTypes;
/**
* Create a new instance of <code>MethodCacheKey</code> with the supplied
* method name and parameter list.
* @param name the name of the method
* @param parameterTypes the arguments in the method signature
*/
public MethodCacheKey(String name, Class[] parameterTypes) {
this.name = name;
this.parameterTypes = (parameterTypes != null ? parameterTypes : new Class[0]);
}
public boolean equals(Object other) {
if (other == this) {
return true;
}
MethodCacheKey otherKey = (MethodCacheKey) other;
return (this.name.equals(otherKey.name) && Arrays.equals(this.parameterTypes, otherKey.parameterTypes));
}
public int hashCode() {
return this.name.hashCode();
}
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?