1 /* 2 * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.jmx.mbeanserver; 27 28 import static com.sun.jmx.mbeanserver.Util.*; 29 30 import java.lang.reflect.Method; 31 import java.util.Map; 32 33 import javax.management.Attribute; 34 import javax.management.MBeanServerConnection; 35 import javax.management.NotCompliantMBeanException; 36 import javax.management.ObjectName; 37 38 /** 39 <p>Helper class for an {@link InvocationHandler} that forwards methods from an 40 MXBean interface to a named 41 MXBean in an MBean Server and handles translation between the 42 arbitrary Java types in the interface and the Open Types used 43 by the MXBean.</p> 44 45 @since 1.6 46 */ 47 public class MXBeanProxy { MXBeanProxy(Class<?> mxbeanInterface)48 public MXBeanProxy(Class<?> mxbeanInterface) { 49 50 if (mxbeanInterface == null) 51 throw new IllegalArgumentException("Null parameter"); 52 53 final MBeanAnalyzer<ConvertingMethod> analyzer; 54 try { 55 analyzer = 56 MXBeanIntrospector.getInstance().getAnalyzer(mxbeanInterface); 57 } catch (NotCompliantMBeanException e) { 58 throw new IllegalArgumentException(e); 59 } 60 analyzer.visit(new Visitor()); 61 } 62 63 private class Visitor 64 implements MBeanAnalyzer.MBeanVisitor<ConvertingMethod> { visitAttribute(String attributeName, ConvertingMethod getter, ConvertingMethod setter)65 public void visitAttribute(String attributeName, 66 ConvertingMethod getter, 67 ConvertingMethod setter) { 68 if (getter != null) { 69 getter.checkCallToOpen(); 70 Method getterMethod = getter.getMethod(); 71 handlerMap.put(getterMethod, 72 new GetHandler(attributeName, getter)); 73 } 74 if (setter != null) { 75 // return type is void, no need for checkCallToOpen 76 Method setterMethod = setter.getMethod(); 77 handlerMap.put(setterMethod, 78 new SetHandler(attributeName, setter)); 79 } 80 } 81 visitOperation(String operationName, ConvertingMethod operation)82 public void visitOperation(String operationName, 83 ConvertingMethod operation) { 84 operation.checkCallToOpen(); 85 Method operationMethod = operation.getMethod(); 86 String[] sig = operation.getOpenSignature(); 87 handlerMap.put(operationMethod, 88 new InvokeHandler(operationName, sig, operation)); 89 } 90 } 91 92 private static abstract class Handler { Handler(String name, ConvertingMethod cm)93 Handler(String name, ConvertingMethod cm) { 94 this.name = name; 95 this.convertingMethod = cm; 96 } 97 getName()98 String getName() { 99 return name; 100 } 101 getConvertingMethod()102 ConvertingMethod getConvertingMethod() { 103 return convertingMethod; 104 } 105 invoke(MBeanServerConnection mbsc, ObjectName name, Object[] args)106 abstract Object invoke(MBeanServerConnection mbsc, 107 ObjectName name, Object[] args) throws Exception; 108 109 private final String name; 110 private final ConvertingMethod convertingMethod; 111 } 112 113 private static class GetHandler extends Handler { GetHandler(String attributeName, ConvertingMethod cm)114 GetHandler(String attributeName, ConvertingMethod cm) { 115 super(attributeName, cm); 116 } 117 118 @Override invoke(MBeanServerConnection mbsc, ObjectName name, Object[] args)119 Object invoke(MBeanServerConnection mbsc, ObjectName name, Object[] args) 120 throws Exception { 121 assert(args == null || args.length == 0); 122 return mbsc.getAttribute(name, getName()); 123 } 124 } 125 126 private static class SetHandler extends Handler { SetHandler(String attributeName, ConvertingMethod cm)127 SetHandler(String attributeName, ConvertingMethod cm) { 128 super(attributeName, cm); 129 } 130 131 @Override invoke(MBeanServerConnection mbsc, ObjectName name, Object[] args)132 Object invoke(MBeanServerConnection mbsc, ObjectName name, Object[] args) 133 throws Exception { 134 assert(args.length == 1); 135 Attribute attr = new Attribute(getName(), args[0]); 136 mbsc.setAttribute(name, attr); 137 return null; 138 } 139 } 140 141 private static class InvokeHandler extends Handler { InvokeHandler(String operationName, String[] signature, ConvertingMethod cm)142 InvokeHandler(String operationName, String[] signature, 143 ConvertingMethod cm) { 144 super(operationName, cm); 145 this.signature = signature; 146 } 147 invoke(MBeanServerConnection mbsc, ObjectName name, Object[] args)148 Object invoke(MBeanServerConnection mbsc, ObjectName name, Object[] args) 149 throws Exception { 150 return mbsc.invoke(name, getName(), args, signature); 151 } 152 153 private final String[] signature; 154 } 155 invoke(MBeanServerConnection mbsc, ObjectName name, Method method, Object[] args)156 public Object invoke(MBeanServerConnection mbsc, ObjectName name, 157 Method method, Object[] args) 158 throws Throwable { 159 160 Handler handler = handlerMap.get(method); 161 ConvertingMethod cm = handler.getConvertingMethod(); 162 MXBeanLookup lookup = MXBeanLookup.lookupFor(mbsc); 163 MXBeanLookup oldLookup = MXBeanLookup.getLookup(); 164 try { 165 MXBeanLookup.setLookup(lookup); 166 Object[] openArgs = cm.toOpenParameters(lookup, args); 167 Object result = handler.invoke(mbsc, name, openArgs); 168 return cm.fromOpenReturnValue(lookup, result); 169 } finally { 170 MXBeanLookup.setLookup(oldLookup); 171 } 172 } 173 174 private final Map<Method, Handler> handlerMap = newMap(); 175 } 176