Source for javax.management.JMX

   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: }