Frames | No Frames |
1: /* JMX.java -- Static methods pertaining to the management API. 2: Copyright (C) 2007 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: package javax.management; 39: 40: import java.lang.reflect.Proxy; 41: 42: /** 43: * Common static methods pertaining to the management 44: * API. There are no instances of this class. 45: * 46: * @author Andrew John Hughes (gnu_andrew@member.fsf.org) 47: * @since 1.6 48: */ 49: public class JMX 50: { 51: 52: /** 53: * The name of the defaultValue field. 54: */ 55: public static final String DEFAULT_VALUE_FIELD = "defaultValue"; 56: 57: /** 58: * The name of the immutableInfo field. 59: */ 60: public static final String IMMUTABLE_INFO_FIELD = "immutableInfo"; 61: 62: /** 63: * The name of the interfaceClassName field. 64: */ 65: public static final String INTERFACE_CLASS_NAME_FIELD = "interfaceClassName"; 66: 67: /** 68: * The name of the legalValues field. 69: */ 70: public static final String LEGAL_VALUES_FIELD = "legalValues"; 71: 72: /** 73: * The name of the maxValue field. 74: */ 75: public static final String MAX_VALUE_FIELD = "maxValue"; 76: 77: /** 78: * The name of the minValue field. 79: */ 80: public static final String MIN_VALUE_FIELD = "minValue"; 81: 82: /** 83: * The name of the mxbean field. 84: */ 85: public static final String MXBEAN_FIELD = "mxbean"; 86: 87: /** 88: * The name of the openType field. 89: */ 90: public static final String OPEN_TYPE_FIELD = "openType"; 91: 92: /** 93: * The name of the originalType field. 94: */ 95: public static final String ORIGINAL_TYPE_FIELD = "originalType"; 96: 97: /** 98: * Prevent instance creation. 99: */ 100: private JMX() 101: { 102: } 103: 104: /** 105: * <p> 106: * Returns true if the given class represents an {@link MXBean} 107: * interface. An interface is an {@link MXBean interface} if: 108: * </p> 109: * <ul> 110: * <li>It is annotated with {@code @MXBean} or 111: * {@code @MXBean(true)}</li>. 112: * <li>Its name ends in {@code "MXBean"} and it does not 113: * have an {@link MXBean} annotation.</li> 114: * </ul> 115: * 116: * @param iface the interface class that is to be checked 117: * for {@link MXBean} status. 118: * @return true if the interface represents an {@link MXBean}. 119: * @throws NullPointerException if {@code iface} is {@code null}. 120: */ 121: public static boolean isMXBeanInterface(Class<?> iface) 122: { 123: MXBean annotation = iface.getAnnotation(MXBean.class); 124: if (annotation != null) 125: return annotation.value(); 126: return iface.getName().endsWith("MXBean"); 127: } 128: 129: /** 130: * <p> 131: * Returns a proxy for a standard management bean, using 132: * the specified connection to access the named implementation. 133: * To create a proxy for the bean, {@code SomethingMBean}, a call to 134: * {@code JMX.newMBeanProxy(server, name, SomethingMBean.class)} 135: * is made, where {@code server} is a local or remote management 136: * server, and {@code name} is the registered {@link ObjectName} 137: * of the implementation of {@code SomethingMBean} to use. 138: * </p> 139: * <p> 140: * The proxy redirects calls to the methods of the interface, 141: * {@link SomethingMBean}, to the appropriate methods of the 142: * management server. If {@link SomethingMBean} is specified 143: * as follows: 144: * </p> 145: * <pre> 146: * public interface SomethingMBean 147: * { 148: * String getName(); 149: * void setName(String name); 150: * void doStuff(); 151: * } 152: * </pre> 153: * <p> 154: * The proxy created above will provide these three methods 155: * using an instance of {@link MBeanServerInvocationHandler}. 156: * The two methods, {@code getName} and {@code setName} define 157: * an attribute, {@code Name}, so a call to {@code getName()} 158: * will return the value of {@code server.getAttribute(name, 159: * "Name")}, while {@code setName(newName)} will result in a 160: * call to {@code server.setAttribute(name, new Attribute("Name", 161: * newName))}. Finally, {@code doStuff()}, as an operation, 162: * will cause the proxy to call {@link MBeanServer#invoke(ObjectName, 163: * String, Object[], String[])} as 164: * {@code server.invoke(name, "doStuff", null, null)}. 165: * </p> 166: * <p> 167: * Calling this method is equivalent to calling 168: * {@link #newMBeanProxy(MBeanServerConnection, ObjectName, Class, 169: * boolean)}. 170: * </p> 171: * 172: * @param conn the server connection over which to forward calls to 173: * the bean. 174: * @param name the registered name of the bean to use to implement 175: * the given interface. 176: * @param iface the interface to provide a proxy for. 177: * @return a proxy implementing the specified interface using calls 178: * to the methods of the bean registered with the supplied 179: * server using the given name. 180: * @see #newMBeanProxy(MBeanServerConnection, ObjectName, Class, 181: * boolean) 182: */ 183: public static <T> T newMBeanProxy(MBeanServerConnection conn, 184: ObjectName name, Class<T> iface) 185: { 186: return newMBeanProxy(conn, name, iface, false); 187: } 188: 189: /** 190: * Returns a proxy for a standard management bean, using 191: * the specified connection to access the named implementation, 192: * as with {@link #newMBeanProxy(MBeanServerConnection, ObjectName, 193: * Class)}. In addition, the proxy returned by this method will 194: * also implement {@link NotificationEmitter} if {@code bcast} is 195: * true, under the assumption that the implementation referenced by 196: * {@code name} implements this interface. Calls to the methods of 197: * {@link NotificationEmitter} will be forwarded to the bean 198: * implementation via the appropriate server methods. 199: * 200: * @param conn the server connection over which to forward calls to 201: * the bean. 202: * @param name the registered name of the bean to use to implement 203: * the given interface. 204: * @param iface the interface to provide a proxy for. 205: * @param bcast true if the proxy should implement 206: * {@link NotificationEmitter}. 207: * @return a proxy implementing the specified interface using calls 208: * to the methods of the bean registered with the supplied 209: * server using the given name. 210: * @see #newMBeanProxy(MBeanServerConnection, ObjectName, Class) 211: */ 212: public static <T> T newMBeanProxy(MBeanServerConnection conn, 213: ObjectName name, Class<T> iface, 214: boolean bcast) 215: { 216: return MBeanServerInvocationHandler.newProxyInstance(conn, name, 217: iface, bcast); 218: } 219: 220: /** 221: * <p> 222: * Returns a proxy for a {@link MXBean}, using the specified 223: * connection to access the named implementation. 224: * To create a proxy for the bean, {@code SomethingMXBean}, a call to 225: * {@code JMX.newMXBeanProxy(server, name, SomethingMXBean.class)} 226: * is made, where {@code server} is a local or remote management 227: * server, and {@code name} is the registered {@link ObjectName} 228: * of the implementation of {@code SomethingMBean} to use. 229: * </p> 230: * <p> 231: * The proxy redirects calls to the methods of the interface, 232: * {@link SomethingMXBean}, to the appropriate methods of the 233: * management server with appropriate conversion between 234: * Java and open types, according to the MXBean rules. If 235: * {@link SomethingMXBean} is specified as follows: 236: * </p> 237: * <pre> 238: * public interface SomethingMXBean 239: * { 240: * String getName(); 241: * void setName(String name); 242: * List<Double> getStatistics(); 243: * void setStatistics(List<Double> statistics); 244: * List<Double> getNamedStatistics(String, Map<String,Integer>); 245: * } 246: * </pre> 247: * <p> 248: * The proxy created above will provide these five methods 249: * using an instance of {@link MBeanServerInvocationHandler}. 250: * The two methods, {@code getName} and {@code setName} define 251: * an attribute, {@code Name}, so a call to {@code getName()} 252: * will return the value of {@code server.getAttribute(name, 253: * "Name")}, while {@code setName(newName)} will result in a 254: * call to {@code server.setAttribute(name, new Attribute("Name", 255: * newName))}. As this uses a simple type, {@link String}, no 256: * conversion is necessary. 257: * </p> 258: * <p> 259: * The two methods, {@code getStatistics} and {@code setStatistics} 260: * similarly define another attribute, {@code Statistics}. Calling 261: * {@code getStatistics()} will cause a call to the server to be 262: * made as before, {@code server.getAttribute(name, "Statistics")}. 263: * However, the type of the return value from this call will be 264: * an array of {@link Double} objects, as per the {@link MXBean} 265: * rules. The proxy converts this back in to a {@link java.util.List} 266: * of {@link Double} objects before returning it. 267: * </p> 268: * <p> 269: * The same process is applied in reverse for 270: * {@code setStatistics(newStats)}. The list is converted into 271: * an appropriate array before the call to 272: * {@link MBeanServerConnection#setAttribute(ObjectName, Attribute)} 273: * is made. Finally, a call to {@code getNamedStatistics} will require 274: * both a Java to open type conversion on the arguments, and then 275: * an open type to Java conversion of the return value. Thus, a proxy 276: * enables an {@link MXBean} to be used in cases where the appropriate 277: * Java types are available and the user wishes to access the bean 278: * using the types directly defined in its interface, just as with 279: * standard management beans. 280: * </p> 281: * <p> 282: * Calling this method is equivalent to calling 283: * {@link #newMXBeanProxy(MBeanServerConnection, ObjectName, Class, 284: * boolean)}. 285: * </p> 286: * 287: * @param conn the server connection over which to forward calls to 288: * the bean. 289: * @param name the registered name of the bean to use to implement 290: * the given interface. 291: * @param iface the interface to provide a proxy for. 292: * @return a proxy implementing the specified interface using calls 293: * to the methods of the bean registered with the supplied 294: * server using the given name. 295: * @see #newMXBeanProxy(MBeanServerConnection, ObjectName, Class, 296: * boolean) 297: */ 298: public static <T> T newMXBeanProxy(MBeanServerConnection conn, 299: ObjectName name, Class<T> iface) 300: { 301: return newMXBeanProxy(conn, name, iface, false); 302: } 303: 304: /** 305: * Returns a proxy for a {@link MXBean}, using 306: * the specified connection to access the named implementation, 307: * as with {@link #newMXBeanProxy(MBeanServerConnection, ObjectName, 308: * Class)}. In addition, the proxy returned by this method will 309: * also implement {@link NotificationEmitter} if {@code bcast} is 310: * true, under the assumption that the implementation referenced by 311: * {@code name} implements this interface. Calls to the methods of 312: * {@link NotificationEmitter} will be forwarded to the bean 313: * implementation via the appropriate server methods. 314: * 315: * @param conn the server connection over which to forward calls to 316: * the bean. 317: * @param name the registered name of the bean to use to implement 318: * the given interface. 319: * @param iface the interface to provide a proxy for. 320: * @param bcast true if the proxy should implement 321: * {@link NotificationEmitter}. 322: * @return a proxy implementing the specified interface using calls 323: * to the methods of the bean registered with the supplied 324: * server using the given name. 325: * @see #newMXBeanProxy(MBeanServerConnection, ObjectName, Class) 326: */ 327: // Suppress warnings as we know an instance of T will be returned. 328: @SuppressWarnings("unchecked") 329: public static <T> T newMXBeanProxy(MBeanServerConnection conn, 330: ObjectName name, Class<T> iface, 331: boolean bcast) 332: { 333: if (bcast) 334: return (T) Proxy.newProxyInstance(iface.getClassLoader(), 335: new Class[] { iface, 336: NotificationEmitter.class }, 337: new MBeanServerInvocationHandler(conn,name,true)); 338: else 339: return (T) Proxy.newProxyInstance(iface.getClassLoader(), 340: new Class[] { iface }, 341: new MBeanServerInvocationHandler(conn,name,true)); 342: } 343: 344: }