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

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