Home » openjdk-7 » javax » management » [javadoc | source]

    1   /*
    2    * Copyright (c) 1999, 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 javax.management;
   27   
   28   import com.sun.jmx.defaults.JmxProperties;
   29   import static com.sun.jmx.defaults.JmxProperties.JMX_INITIAL_BUILDER;
   30   import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER;
   31   import com.sun.jmx.mbeanserver.GetPropertyAction;
   32   import java.security.AccessController;
   33   import java.security.Permission;
   34   import java.util.ArrayList;
   35   import java.util.logging.Level;
   36   import javax.management.loading.ClassLoaderRepository;
   37   
   38   
   39   /**
   40    * <p>Provides MBean server references.  There are no instances of
   41    * this class.</p>
   42    *
   43    * <p>Since JMX 1.2 this class makes it possible to replace the default
   44    * MBeanServer implementation. This is done using the
   45    * {@link javax.management.MBeanServerBuilder} class.
   46    * The class of the initial MBeanServerBuilder to be
   47    * instantiated can be specified through the
   48    * <b>javax.management.builder.initial</b> system property.
   49    * The specified class must be a public subclass of
   50    * {@link javax.management.MBeanServerBuilder}, and must have a public
   51    * empty constructor.
   52    * <p>By default, if no value for that property is specified, an instance of
   53    * {@link
   54    * javax.management.MBeanServerBuilder javax.management.MBeanServerBuilder}
   55    * is created. Otherwise, the MBeanServerFactory attempts to load the
   56    * specified class using
   57    * {@link java.lang.Thread#getContextClassLoader()
   58    *   Thread.currentThread().getContextClassLoader()}, or if that is null,
   59    * {@link java.lang.Class#forName(java.lang.String) Class.forName()}. Then
   60    * it creates an initial instance of that Class using
   61    * {@link java.lang.Class#newInstance()}. If any checked exception
   62    * is raised during this process (e.g.
   63    * {@link java.lang.ClassNotFoundException},
   64    * {@link java.lang.InstantiationException}) the MBeanServerFactory
   65    * will propagate this exception from within a RuntimeException.</p>
   66    *
   67    * <p>The <b>javax.management.builder.initial</b> system property is
   68    * consulted every time a new MBeanServer needs to be created, and the
   69    * class pointed to by that property is loaded. If that class is different
   70    * from that of the current MBeanServerBuilder, then a new MBeanServerBuilder
   71    * is created. Otherwise, the MBeanServerFactory may create a new
   72    * MBeanServerBuilder or reuse the current one.</p>
   73    *
   74    * <p>If the class pointed to by the property cannot be
   75    * loaded, or does not correspond to a valid subclass of MBeanServerBuilder
   76    * then an exception is propagated, and no MBeanServer can be created until
   77    * the <b>javax.management.builder.initial</b> system property is reset to
   78    * valid value.</p>
   79    *
   80    * <p>The MBeanServerBuilder makes it possible to wrap the MBeanServers
   81    * returned by the default MBeanServerBuilder implementation, for the purpose
   82    * of e.g. adding an additional security layer.</p>
   83    *
   84    * @since 1.5
   85    */
   86   public class MBeanServerFactory {
   87   
   88       /*
   89        * There are no instances of this class so don't generate the
   90        * default public constructor.
   91        */
   92       private MBeanServerFactory() {
   93   
   94       }
   95   
   96       /**
   97        * The builder that will be used to construct MBeanServers.
   98        *
   99        **/
  100       private static MBeanServerBuilder builder = null;
  101   
  102       /**
  103        * Provide a new {@link javax.management.MBeanServerBuilder}.
  104        * @param builder The new MBeanServerBuilder that will be used to
  105        *        create {@link javax.management.MBeanServer}s.
  106        * @exception IllegalArgumentException if the given builder is null.
  107        *
  108        * @exception SecurityException if there is a SecurityManager and
  109        * the caller's permissions do not include or imply <code>{@link
  110        * MBeanServerPermission}("setMBeanServerBuilder")</code>.
  111        *
  112        **/
  113       // public static synchronized void
  114       //    setMBeanServerBuilder(MBeanServerBuilder builder) {
  115       //    checkPermission("setMBeanServerBuilder");
  116       //    MBeanServerFactory.builder = builder;
  117       // }
  118   
  119       /**
  120        * Get the current {@link javax.management.MBeanServerBuilder}.
  121        *
  122        * @return the current {@link javax.management.MBeanServerBuilder}.
  123        *
  124        * @exception SecurityException if there is a SecurityManager and
  125        * the caller's permissions do not include or imply <code>{@link
  126        * MBeanServerPermission}("getMBeanServerBuilder")</code>.
  127        *
  128        **/
  129       // public static synchronized MBeanServerBuilder getMBeanServerBuilder() {
  130       //     checkPermission("getMBeanServerBuilder");
  131       //     return builder;
  132       // }
  133   
  134       /**
  135        * Remove internal MBeanServerFactory references to a created
  136        * MBeanServer. This allows the garbage collector to remove the
  137        * MBeanServer object.
  138        *
  139        * @param mbeanServer the MBeanServer object to remove.
  140        *
  141        * @exception java.lang.IllegalArgumentException if
  142        * <code>mbeanServer</code> was not generated by one of the
  143        * <code>createMBeanServer</code> methods, or if
  144        * <code>releaseMBeanServer</code> was already called on it.
  145        *
  146        * @exception SecurityException if there is a SecurityManager and
  147        * the caller's permissions do not include or imply <code>{@link
  148        * MBeanServerPermission}("releaseMBeanServer")</code>.
  149        */
  150       public static void releaseMBeanServer(MBeanServer mbeanServer) {
  151           checkPermission("releaseMBeanServer");
  152   
  153           removeMBeanServer(mbeanServer);
  154       }
  155   
  156       /**
  157        * <p>Return a new object implementing the MBeanServer interface
  158        * with a standard default domain name.  The default domain name
  159        * is used as the domain part in the ObjectName of MBeans when the
  160        * domain is specified by the user is null.</p>
  161        *
  162        * <p>The standard default domain name is
  163        * <code>DefaultDomain</code>.</p>
  164        *
  165        * <p>The MBeanServer reference is internally kept. This will
  166        * allow <CODE>findMBeanServer</CODE> to return a reference to
  167        * this MBeanServer object.</p>
  168        *
  169        * <p>This method is equivalent to <code>createMBeanServer(null)</code>.
  170        *
  171        * @return the newly created MBeanServer.
  172        *
  173        * @exception SecurityException if there is a SecurityManager and the
  174        * caller's permissions do not include or imply <code>{@link
  175        * MBeanServerPermission}("createMBeanServer")</code>.
  176        *
  177        * @exception JMRuntimeException if the property
  178        * <code>javax.management.builder.initial</code> exists but the
  179        * class it names cannot be instantiated through a public
  180        * no-argument constructor; or if the instantiated builder returns
  181        * null from its {@link MBeanServerBuilder#newMBeanServerDelegate
  182        * newMBeanServerDelegate} or {@link
  183        * MBeanServerBuilder#newMBeanServer newMBeanServer} methods.
  184        *
  185        * @exception ClassCastException if the property
  186        * <code>javax.management.builder.initial</code> exists and can be
  187        * instantiated but is not assignment compatible with {@link
  188        * MBeanServerBuilder}.
  189        */
  190       public static MBeanServer createMBeanServer() {
  191           return createMBeanServer(null);
  192       }
  193   
  194       /**
  195        * <p>Return a new object implementing the {@link MBeanServer}
  196        * interface with the specified default domain name.  The given
  197        * domain name is used as the domain part in the ObjectName of
  198        * MBeans when the domain is specified by the user is null.</p>
  199        *
  200        * <p>The MBeanServer reference is internally kept. This will
  201        * allow <CODE>findMBeanServer</CODE> to return a reference to
  202        * this MBeanServer object.</p>
  203        *
  204        * @param domain the default domain name for the created
  205        * MBeanServer.  This is the value that will be returned by {@link
  206        * MBeanServer#getDefaultDomain}.
  207        *
  208        * @return the newly created MBeanServer.
  209        *
  210        * @exception SecurityException if there is a SecurityManager and
  211        * the caller's permissions do not include or imply <code>{@link
  212        * MBeanServerPermission}("createMBeanServer")</code>.
  213        *
  214        * @exception JMRuntimeException if the property
  215        * <code>javax.management.builder.initial</code> exists but the
  216        * class it names cannot be instantiated through a public
  217        * no-argument constructor; or if the instantiated builder returns
  218        * null from its {@link MBeanServerBuilder#newMBeanServerDelegate
  219        * newMBeanServerDelegate} or {@link
  220        * MBeanServerBuilder#newMBeanServer newMBeanServer} methods.
  221        *
  222        * @exception ClassCastException if the property
  223        * <code>javax.management.builder.initial</code> exists and can be
  224        * instantiated but is not assignment compatible with {@link
  225        * MBeanServerBuilder}.
  226        */
  227       public static MBeanServer createMBeanServer(String domain)  {
  228           checkPermission("createMBeanServer");
  229   
  230           final MBeanServer mBeanServer = newMBeanServer(domain);
  231           addMBeanServer(mBeanServer);
  232           return mBeanServer;
  233       }
  234   
  235       /**
  236        * <p>Return a new object implementing the MBeanServer interface
  237        * with a standard default domain name, without keeping an
  238        * internal reference to this new object.  The default domain name
  239        * is used as the domain part in the ObjectName of MBeans when the
  240        * domain is specified by the user is null.</p>
  241        *
  242        * <p>The standard default domain name is
  243        * <code>DefaultDomain</code>.</p>
  244        *
  245        * <p>No reference is kept. <CODE>findMBeanServer</CODE> will not
  246        * be able to return a reference to this MBeanServer object, but
  247        * the garbage collector will be able to remove the MBeanServer
  248        * object when it is no longer referenced.</p>
  249        *
  250        * <p>This method is equivalent to <code>newMBeanServer(null)</code>.</p>
  251        *
  252        * @return the newly created MBeanServer.
  253        *
  254        * @exception SecurityException if there is a SecurityManager and the
  255        * caller's permissions do not include or imply <code>{@link
  256        * MBeanServerPermission}("newMBeanServer")</code>.
  257        *
  258        * @exception JMRuntimeException if the property
  259        * <code>javax.management.builder.initial</code> exists but the
  260        * class it names cannot be instantiated through a public
  261        * no-argument constructor; or if the instantiated builder returns
  262        * null from its {@link MBeanServerBuilder#newMBeanServerDelegate
  263        * newMBeanServerDelegate} or {@link
  264        * MBeanServerBuilder#newMBeanServer newMBeanServer} methods.
  265        *
  266        * @exception ClassCastException if the property
  267        * <code>javax.management.builder.initial</code> exists and can be
  268        * instantiated but is not assignment compatible with {@link
  269        * MBeanServerBuilder}.
  270        */
  271       public static MBeanServer newMBeanServer() {
  272           return newMBeanServer(null);
  273       }
  274   
  275       /**
  276        * <p>Return a new object implementing the MBeanServer interface
  277        * with the specified default domain name, without keeping an
  278        * internal reference to this new object.  The given domain name
  279        * is used as the domain part in the ObjectName of MBeans when the
  280        * domain is specified by the user is null.</p>
  281        *
  282        * <p>No reference is kept. <CODE>findMBeanServer</CODE> will not
  283        * be able to return a reference to this MBeanServer object, but
  284        * the garbage collector will be able to remove the MBeanServer
  285        * object when it is no longer referenced.</p>
  286        *
  287        * @param domain the default domain name for the created
  288        * MBeanServer.  This is the value that will be returned by {@link
  289        * MBeanServer#getDefaultDomain}.
  290        *
  291        * @return the newly created MBeanServer.
  292        *
  293        * @exception SecurityException if there is a SecurityManager and the
  294        * caller's permissions do not include or imply <code>{@link
  295        * MBeanServerPermission}("newMBeanServer")</code>.
  296        *
  297        * @exception JMRuntimeException if the property
  298        * <code>javax.management.builder.initial</code> exists but the
  299        * class it names cannot be instantiated through a public
  300        * no-argument constructor; or if the instantiated builder returns
  301        * null from its {@link MBeanServerBuilder#newMBeanServerDelegate
  302        * newMBeanServerDelegate} or {@link
  303        * MBeanServerBuilder#newMBeanServer newMBeanServer} methods.
  304        *
  305        * @exception ClassCastException if the property
  306        * <code>javax.management.builder.initial</code> exists and can be
  307        * instantiated but is not assignment compatible with {@link
  308        * MBeanServerBuilder}.
  309        */
  310       public static MBeanServer newMBeanServer(String domain)  {
  311           checkPermission("newMBeanServer");
  312   
  313           // Get the builder. Creates a new one if necessary.
  314           //
  315           final MBeanServerBuilder mbsBuilder = getNewMBeanServerBuilder();
  316           // Returned value cannot be null.  NullPointerException if violated.
  317   
  318           synchronized(mbsBuilder) {
  319               final MBeanServerDelegate delegate  =
  320                       mbsBuilder.newMBeanServerDelegate();
  321               if (delegate == null) {
  322                   final String msg =
  323                           "MBeanServerBuilder.newMBeanServerDelegate() " +
  324                           "returned null";
  325                   throw new JMRuntimeException(msg);
  326               }
  327               final MBeanServer mbeanServer =
  328                       mbsBuilder.newMBeanServer(domain,null,delegate);
  329               if (mbeanServer == null) {
  330                   final String msg =
  331                           "MBeanServerBuilder.newMBeanServer() returned null";
  332                   throw new JMRuntimeException(msg);
  333               }
  334               return mbeanServer;
  335           }
  336       }
  337   
  338       /**
  339        * <p>Return a list of registered MBeanServer objects.  A
  340        * registered MBeanServer object is one that was created by one of
  341        * the <code>createMBeanServer</code> methods and not subsequently
  342        * released with <code>releaseMBeanServer</code>.</p>
  343        *
  344        * @param agentId The agent identifier of the MBeanServer to
  345        * retrieve.  If this parameter is null, all registered
  346        * MBeanServers in this JVM are returned.  Otherwise, only
  347        * MBeanServers whose id is equal to <code>agentId</code> are
  348        * returned.  The id of an MBeanServer is the
  349        * <code>MBeanServerId</code> attribute of its delegate MBean.
  350        *
  351        * @return A list of MBeanServer objects.
  352        *
  353        * @exception SecurityException if there is a SecurityManager and the
  354        * caller's permissions do not include or imply <code>{@link
  355        * MBeanServerPermission}("findMBeanServer")</code>.
  356        */
  357       public synchronized static
  358               ArrayList<MBeanServer> findMBeanServer(String agentId) {
  359   
  360           checkPermission("findMBeanServer");
  361   
  362           if (agentId == null)
  363               return new ArrayList<MBeanServer>(mBeanServerList);
  364   
  365           ArrayList<MBeanServer> result = new ArrayList<MBeanServer>();
  366           for (MBeanServer mbs : mBeanServerList) {
  367               String name = mBeanServerId(mbs);
  368               if (agentId.equals(name))
  369                   result.add(mbs);
  370           }
  371           return result;
  372       }
  373   
  374       /**
  375        * Return the ClassLoaderRepository used by the given MBeanServer.
  376        * This method is equivalent to {@link
  377        * MBeanServer#getClassLoaderRepository() server.getClassLoaderRepository()}.
  378        * @param server The MBeanServer under examination. Since JMX 1.2,
  379        * if <code>server</code> is <code>null</code>, the result is a
  380        * {@link NullPointerException}.  This behavior differs from what
  381        * was implemented in JMX 1.1 - where the possibility to use
  382        * <code>null</code> was deprecated.
  383        * @return The Class Loader Repository used by the given MBeanServer.
  384        * @exception SecurityException if there is a SecurityManager and
  385        * the caller's permissions do not include or imply <code>{@link
  386        * MBeanPermission}("getClassLoaderRepository")</code>.
  387        *
  388        * @exception NullPointerException if <code>server</code> is null.
  389        *
  390        **/
  391       public static ClassLoaderRepository getClassLoaderRepository(
  392               MBeanServer server) {
  393           return server.getClassLoaderRepository();
  394       }
  395   
  396       private static String mBeanServerId(MBeanServer mbs) {
  397           try {
  398               return (String) mbs.getAttribute(MBeanServerDelegate.DELEGATE_NAME,
  399                       "MBeanServerId");
  400           } catch (JMException e) {
  401               JmxProperties.MISC_LOGGER.finest(
  402                       "Ignoring exception while getting MBeanServerId: "+e);
  403               return null;
  404           }
  405       }
  406   
  407       private static void checkPermission(String action)
  408       throws SecurityException {
  409           SecurityManager sm = System.getSecurityManager();
  410           if (sm != null) {
  411               Permission perm = new MBeanServerPermission(action);
  412               sm.checkPermission(perm);
  413           }
  414       }
  415   
  416       private static synchronized void addMBeanServer(MBeanServer mbs) {
  417           mBeanServerList.add(mbs);
  418       }
  419   
  420       private static synchronized void removeMBeanServer(MBeanServer mbs) {
  421           boolean removed = mBeanServerList.remove(mbs);
  422           if (!removed) {
  423               MBEANSERVER_LOGGER.logp(Level.FINER,
  424                       MBeanServerFactory.class.getName(),
  425                       "removeMBeanServer(MBeanServer)",
  426                       "MBeanServer was not in list!");
  427               throw new IllegalArgumentException("MBeanServer was not in list!");
  428           }
  429       }
  430   
  431       private static final ArrayList<MBeanServer> mBeanServerList =
  432               new ArrayList<MBeanServer>();
  433   
  434       /**
  435        * Load the builder class through the context class loader.
  436        * @param builderClassName The name of the builder class.
  437        **/
  438       private static Class<?> loadBuilderClass(String builderClassName)
  439       throws ClassNotFoundException {
  440           final ClassLoader loader =
  441                   Thread.currentThread().getContextClassLoader();
  442   
  443           if (loader != null) {
  444               // Try with context class loader
  445               return loader.loadClass(builderClassName);
  446           }
  447   
  448           // No context class loader? Try with Class.forName()
  449           return Class.forName(builderClassName);
  450       }
  451   
  452       /**
  453        * Creates the initial builder according to the
  454        * javax.management.builder.initial System property - if specified.
  455        * If any checked exception needs to be thrown, it is embedded in
  456        * a JMRuntimeException.
  457        **/
  458       private static MBeanServerBuilder newBuilder(Class<?> builderClass) {
  459           try {
  460               final Object abuilder = builderClass.newInstance();
  461               return (MBeanServerBuilder)abuilder;
  462           } catch (RuntimeException x) {
  463               throw x;
  464           } catch (Exception x) {
  465               final String msg =
  466                       "Failed to instantiate a MBeanServerBuilder from " +
  467                       builderClass + ": " + x;
  468               throw new JMRuntimeException(msg, x);
  469           }
  470       }
  471   
  472       /**
  473        * Instantiate a new builder according to the
  474        * javax.management.builder.initial System property - if needed.
  475        **/
  476       private static synchronized void checkMBeanServerBuilder() {
  477           try {
  478               GetPropertyAction act =
  479                       new GetPropertyAction(JMX_INITIAL_BUILDER);
  480               String builderClassName = AccessController.doPrivileged(act);
  481   
  482               try {
  483                   final Class<?> newBuilderClass;
  484                   if (builderClassName == null || builderClassName.length() == 0)
  485                       newBuilderClass = MBeanServerBuilder.class;
  486                   else
  487                       newBuilderClass = loadBuilderClass(builderClassName);
  488   
  489                   // Check whether a new builder needs to be created
  490                   if (builder != null) {
  491                       final Class<?> builderClass = builder.getClass();
  492                       if (newBuilderClass == builderClass)
  493                           return; // no need to create a new builder...
  494                   }
  495   
  496                   // Create a new builder
  497                   builder = newBuilder(newBuilderClass);
  498               } catch (ClassNotFoundException x) {
  499                   final String msg =
  500                           "Failed to load MBeanServerBuilder class " +
  501                           builderClassName + ": " + x;
  502                   throw new JMRuntimeException(msg, x);
  503               }
  504           } catch (RuntimeException x) {
  505               if (MBEANSERVER_LOGGER.isLoggable(Level.FINEST)) {
  506                   StringBuilder strb = new StringBuilder()
  507                   .append("Failed to instantiate MBeanServerBuilder: ").append(x)
  508                   .append("\n\t\tCheck the value of the ")
  509                   .append(JMX_INITIAL_BUILDER).append(" property.");
  510                   MBEANSERVER_LOGGER.logp(Level.FINEST,
  511                           MBeanServerFactory.class.getName(),
  512                           "checkMBeanServerBuilder",
  513                           strb.toString());
  514               }
  515               throw x;
  516           }
  517       }
  518   
  519       /**
  520        * Get the current {@link javax.management.MBeanServerBuilder},
  521        * as specified by the current value of the
  522        * javax.management.builder.initial property.
  523        *
  524        * This method consults the property and instantiates a new builder
  525        * if needed.
  526        *
  527        * @return the new current {@link javax.management.MBeanServerBuilder}.
  528        *
  529        * @exception SecurityException if there is a SecurityManager and
  530        * the caller's permissions do not make it possible to instantiate
  531        * a new builder.
  532        * @exception JMRuntimeException if the builder instantiation
  533        *   fails with a checked exception -
  534        *   {@link java.lang.ClassNotFoundException} etc...
  535        *
  536        **/
  537       private static synchronized MBeanServerBuilder getNewMBeanServerBuilder() {
  538           checkMBeanServerBuilder();
  539           return builder;
  540       }
  541   
  542   }

Home » openjdk-7 » javax » management » [javadoc | source]