001 /* JMX.java -- Static methods pertaining to the management API. 002 Copyright (C) 2007 Free Software Foundation, Inc. 003 004 This file is part of GNU Classpath. 005 006 GNU Classpath is free software; you can redistribute it and/or modify 007 it under the terms of the GNU General Public License as published by 008 the Free Software Foundation; either version 2, or (at your option) 009 any later version. 010 011 GNU Classpath is distributed in the hope that it will be useful, but 012 WITHOUT ANY WARRANTY; without even the implied warranty of 013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 General Public License for more details. 015 016 You should have received a copy of the GNU General Public License 017 along with GNU Classpath; see the file COPYING. If not, write to the 018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 019 02110-1301 USA. 020 021 Linking this library statically or dynamically with other modules is 022 making a combined work based on this library. Thus, the terms and 023 conditions of the GNU General Public License cover the whole 024 combination. 025 026 As a special exception, the copyright holders of this library give you 027 permission to link this library with independent modules to produce an 028 executable, regardless of the license terms of these independent 029 modules, and to copy and distribute the resulting executable under 030 terms of your choice, provided that you also meet, for each linked 031 independent module, the terms and conditions of the license of that 032 module. An independent module is a module which is not derived from 033 or based on this library. If you modify this library, you may extend 034 this exception to your version of the library, but you are not 035 obligated to do so. If you do not wish to do so, delete this 036 exception statement from your version. */ 037 038 package javax.management; 039 040 import java.lang.reflect.Proxy; 041 042 /** 043 * Common static methods pertaining to the management 044 * API. There are no instances of this class. 045 * 046 * @author Andrew John Hughes (gnu_andrew@member.fsf.org) 047 * @since 1.6 048 */ 049 public class JMX 050 { 051 052 /** 053 * The name of the defaultValue field. 054 */ 055 public static final String DEFAULT_VALUE_FIELD = "defaultValue"; 056 057 /** 058 * The name of the immutableInfo field. 059 */ 060 public static final String IMMUTABLE_INFO_FIELD = "immutableInfo"; 061 062 /** 063 * The name of the interfaceClassName field. 064 */ 065 public static final String INTERFACE_CLASS_NAME_FIELD = "interfaceClassName"; 066 067 /** 068 * The name of the legalValues field. 069 */ 070 public static final String LEGAL_VALUES_FIELD = "legalValues"; 071 072 /** 073 * The name of the maxValue field. 074 */ 075 public static final String MAX_VALUE_FIELD = "maxValue"; 076 077 /** 078 * The name of the minValue field. 079 */ 080 public static final String MIN_VALUE_FIELD = "minValue"; 081 082 /** 083 * The name of the mxbean field. 084 */ 085 public static final String MXBEAN_FIELD = "mxbean"; 086 087 /** 088 * The name of the openType field. 089 */ 090 public static final String OPEN_TYPE_FIELD = "openType"; 091 092 /** 093 * The name of the originalType field. 094 */ 095 public static final String ORIGINAL_TYPE_FIELD = "originalType"; 096 097 /** 098 * Prevent instance creation. 099 */ 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 public static <T> T newMXBeanProxy(MBeanServerConnection conn, 328 ObjectName name, Class<T> iface, 329 boolean bcast) 330 { 331 if (bcast) 332 return (T) Proxy.newProxyInstance(iface.getClassLoader(), 333 new Class[] { iface, 334 NotificationEmitter.class }, 335 new MBeanServerInvocationHandler(conn,name,true)); 336 else 337 return (T) Proxy.newProxyInstance(iface.getClassLoader(), 338 new Class[] { iface }, 339 new MBeanServerInvocationHandler(conn,name,true)); 340 } 341 342 }