| /* |
| * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Sun designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Sun in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| * CA 95054 USA or visit www.sun.com if you need additional information or |
| * have any questions. |
| */ |
| |
| package javax.management; |
| |
| import com.sun.jmx.defaults.JmxProperties; |
| import static com.sun.jmx.defaults.JmxProperties.JMX_INITIAL_BUILDER; |
| import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER; |
| import com.sun.jmx.mbeanserver.GetPropertyAction; |
| import com.sun.jmx.mbeanserver.Util; |
| import java.security.AccessController; |
| import java.security.Permission; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.logging.Level; |
| import javax.management.loading.ClassLoaderRepository; |
| |
| |
| /** |
| * <p>Provides MBean server references. There are no instances of |
| * this class.</p> |
| * |
| * <p>Since JMX 1.2 this class makes it possible to replace the default |
| * MBeanServer implementation. This is done using the |
| * {@link javax.management.MBeanServerBuilder} class. |
| * The class of the initial MBeanServerBuilder to be |
| * instantiated can be specified through the |
| * <b>javax.management.builder.initial</b> system property. |
| * The specified class must be a public subclass of |
| * {@link javax.management.MBeanServerBuilder}, and must have a public |
| * empty constructor. |
| * <p>By default, if no value for that property is specified, an instance of |
| * {@link |
| * javax.management.MBeanServerBuilder javax.management.MBeanServerBuilder} |
| * is created. Otherwise, the MBeanServerFactory attempts to load the |
| * specified class using |
| * {@link java.lang.Thread#getContextClassLoader() |
| * Thread.currentThread().getContextClassLoader()}, or if that is null, |
| * {@link java.lang.Class#forName(java.lang.String) Class.forName()}. Then |
| * it creates an initial instance of that Class using |
| * {@link java.lang.Class#newInstance()}. If any checked exception |
| * is raised during this process (e.g. |
| * {@link java.lang.ClassNotFoundException}, |
| * {@link java.lang.InstantiationException}) the MBeanServerFactory |
| * will propagate this exception from within a RuntimeException.</p> |
| * |
| * <p>The <b>javax.management.builder.initial</b> system property is |
| * consulted every time a new MBeanServer needs to be created, and the |
| * class pointed to by that property is loaded. If that class is different |
| * from that of the current MBeanServerBuilder, then a new MBeanServerBuilder |
| * is created. Otherwise, the MBeanServerFactory may create a new |
| * MBeanServerBuilder or reuse the current one.</p> |
| * |
| * <p>If the class pointed to by the property cannot be |
| * loaded, or does not correspond to a valid subclass of MBeanServerBuilder |
| * then an exception is propagated, and no MBeanServer can be created until |
| * the <b>javax.management.builder.initial</b> system property is reset to |
| * valid value.</p> |
| * |
| * <p>The MBeanServerBuilder makes it possible to wrap the MBeanServers |
| * returned by the default MBeanServerBuilder implementation, for the purpose |
| * of e.g. adding an additional security layer.</p> |
| * |
| * <p id="MBeanServerName">Since version 2.0 of the JMX API, when creating |
| * an MBeanServer, |
| * it is possible to specify an {@linkplain #getMBeanServerName |
| * MBean Server name}. |
| * To create an MBean Server with a name, the MBeanServerFactory provides two |
| * new methods:</p> |
| * <ul><li>{@link #createNamedMBeanServer |
| * createNamedMBeanServer(mbeanServerName, defaultDomain)}: creates a named |
| * MBeanServer and keeps an internal reference to the created object. The |
| * MBeanServer can be later retrieved using {@link #findMBeanServer |
| * findMBeanServer(mbeanServerId)} or |
| * {@link #findMBeanServerByName findMBeanServerByName(mbeanServerName)}, and |
| * can be released through {@link |
| * #releaseMBeanServer releaseMBeanServer(mbeanServer)}.</li> |
| * <li>{@link #newNamedMBeanServer |
| * newNamedMBeanServer(mbeanServerName, defaultDomain)}: |
| * creates a named MBeanServer without keeping any internal reference to the |
| * named server.</li> |
| * </ul> |
| * <p>The name of the MBeanServer is stored in the |
| * {@linkplain MBeanServerDelegate MBean Server delegate MBean} |
| * and is embedded in its {@link MBeanServerDelegate#getMBeanServerId |
| * MBeanServerId} attribute.</p> |
| * <p>The name of the MBeanServer is particularly useful when |
| * <a href="MBeanServer.html#security">MBean permissions</a> are checked: |
| * it makes it |
| * possible to distinguish between an MBean named "X" in MBeanServer named |
| * "M1", and another MBean of the same name "X" in another MBeanServer named |
| * "M2".</p> |
| * <p>When naming MBean servers it is recommended to use a name that starts |
| * with a Java package name. It is also recommended that the default domain and |
| * the MBeanServer name be the same.</p> |
| * |
| * @since 1.5 |
| */ |
| public class MBeanServerFactory { |
| |
| /** |
| * The <a href="#MBeanServerName">MBean Server name</a> that will be |
| * checked by a <a href="MBeanServer.html#security">permission you need</a> |
| * when checking access to an MBean registered in an MBeanServer for |
| * which no MBeanServer name was specified. |
| * |
| * @since 1.7 |
| */ |
| public final static String DEFAULT_MBEANSERVER_NAME = "default"; |
| |
| /* |
| * There are no instances of this class so don't generate the |
| * default public constructor. |
| */ |
| private MBeanServerFactory() { |
| |
| } |
| |
| /** |
| * The builder that will be used to construct MBeanServers. |
| * |
| **/ |
| private static MBeanServerBuilder builder = null; |
| |
| /** |
| * Provide a new {@link javax.management.MBeanServerBuilder}. |
| * @param builder The new MBeanServerBuilder that will be used to |
| * create {@link javax.management.MBeanServer}s. |
| * @exception IllegalArgumentException if the given builder is null. |
| * |
| * @exception SecurityException if there is a SecurityManager and |
| * the caller's permissions do not include or imply <code>{@link |
| * MBeanServerPermission}("setMBeanServerBuilder")</code>. |
| * |
| **/ |
| // public static synchronized void |
| // setMBeanServerBuilder(MBeanServerBuilder builder) { |
| // checkPermission("setMBeanServerBuilder"); |
| // MBeanServerFactory.builder = builder; |
| // } |
| |
| /** |
| * Get the current {@link javax.management.MBeanServerBuilder}. |
| * |
| * @return the current {@link javax.management.MBeanServerBuilder}. |
| * |
| * @exception SecurityException if there is a SecurityManager and |
| * the caller's permissions do not include or imply <code>{@link |
| * MBeanServerPermission}("getMBeanServerBuilder")</code>. |
| * |
| **/ |
| // public static synchronized MBeanServerBuilder getMBeanServerBuilder() { |
| // checkPermission("getMBeanServerBuilder"); |
| // return builder; |
| // } |
| |
| /** |
| * Remove internal MBeanServerFactory references to a created |
| * MBeanServer. This allows the garbage collector to remove the |
| * MBeanServer object. |
| * |
| * @param mbeanServer the MBeanServer object to remove. |
| * |
| * @exception java.lang.IllegalArgumentException if |
| * <code>mbeanServer</code> was not generated by one of the |
| * <code>createMBeanServer</code> methods, or if |
| * <code>releaseMBeanServer</code> was already called on it. |
| * |
| * @exception SecurityException if there is a SecurityManager and |
| * the caller's permissions do not include or imply <code>{@link |
| * MBeanServerPermission}("releaseMBeanServer")</code>. |
| */ |
| public static void releaseMBeanServer(MBeanServer mbeanServer) { |
| checkPermission("releaseMBeanServer"); |
| |
| removeMBeanServer(mbeanServer); |
| } |
| |
| /** |
| * <p>Return a new object implementing the MBeanServer interface |
| * with a standard default domain name. The default domain name |
| * is used as the domain part in the ObjectName of MBeans when the |
| * domain is specified by the user is null.</p> |
| * |
| * <p>The standard default domain name is |
| * <code>DefaultDomain</code>.</p> |
| * |
| * <p>The MBeanServer reference is internally kept. This will |
| * allow <CODE>findMBeanServer</CODE> to return a reference to |
| * this MBeanServer object.</p> |
| * |
| * <p>This method is equivalent to <code>createMBeanServer(null)</code>. |
| * |
| * @return the newly created MBeanServer. |
| * |
| * @exception SecurityException if there is a SecurityManager and the |
| * caller's permissions do not include or imply <code>{@link |
| * MBeanServerPermission}("createMBeanServer")</code>. |
| * |
| * @exception JMRuntimeException if the property |
| * <code>javax.management.builder.initial</code> exists but the |
| * class it names cannot be instantiated through a public |
| * no-argument constructor; or if the instantiated builder returns |
| * null from its {@link MBeanServerBuilder#newMBeanServerDelegate |
| * newMBeanServerDelegate} or {@link |
| * MBeanServerBuilder#newMBeanServer newMBeanServer} methods. |
| * |
| * @exception ClassCastException if the property |
| * <code>javax.management.builder.initial</code> exists and can be |
| * instantiated but is not assignment compatible with {@link |
| * MBeanServerBuilder}. |
| */ |
| public static MBeanServer createMBeanServer() { |
| return createMBeanServer(null); |
| } |
| |
| /** |
| * <p>Return a new object implementing the {@link MBeanServer} |
| * interface with the specified default domain name. The given |
| * domain name is used as the domain part in the ObjectName of |
| * MBeans when the domain is specified by the user is null.</p> |
| * |
| * <p>The MBeanServer reference is internally kept. This will |
| * allow <CODE>findMBeanServer</CODE> to return a reference to |
| * this MBeanServer object.</p> |
| * |
| * @param domain the default domain name for the created |
| * MBeanServer. This is the value that will be returned by {@link |
| * MBeanServer#getDefaultDomain}. |
| * |
| * @return the newly created MBeanServer. |
| * |
| * @exception SecurityException if there is a SecurityManager and |
| * the caller's permissions do not include or imply <code>{@link |
| * MBeanServerPermission}("createMBeanServer")</code>. |
| * |
| * @exception JMRuntimeException if the property |
| * <code>javax.management.builder.initial</code> exists but the |
| * class it names cannot be instantiated through a public |
| * no-argument constructor; or if the instantiated builder returns |
| * null from its {@link MBeanServerBuilder#newMBeanServerDelegate |
| * newMBeanServerDelegate} or {@link |
| * MBeanServerBuilder#newMBeanServer newMBeanServer} methods. |
| * |
| * @exception ClassCastException if the property |
| * <code>javax.management.builder.initial</code> exists and can be |
| * instantiated but is not assignment compatible with {@link |
| * MBeanServerBuilder}. |
| * |
| * @see #createNamedMBeanServer |
| */ |
| public static MBeanServer createMBeanServer(String domain) { |
| return createMBeanServer(null,domain); |
| } |
| |
| /** |
| * <p>Return a new object implementing the {@link MBeanServer} |
| * interface with the specified |
| * <a href="#MBeanServerName">MBean Server name</a> |
| * and default domain name. The given MBean server name |
| * is used in <a href="MBeanServer.html#security">security checks</a>, and |
| * can also be used to {@linkplain #findMBeanServerByName(java.lang.String) |
| * find an MBeanServer by name}. The given |
| * domain name is used as the domain part in the ObjectName of |
| * MBeans when the domain is specified by the user is null.</p> |
| * |
| * <p>The MBeanServer reference is internally kept. This will |
| * allow <CODE>findMBeanServer</CODE> to return a reference to |
| * this MBeanServer object.</p> |
| * |
| * @param mbeanServerName the name for the created |
| * MBeanServer. This is the name that will be included in the |
| * {@linkplain MBeanPermission permission you need} when checking |
| * <a href="MBeanServer.html#security">MBean Permissions</a> for accessing |
| * an MBean registered in the returned MBeanServer. The characters |
| * {@code ':'} (colon), {@code ';'} (semicolon), {@code '*'} (star) |
| * and {@code '?'} are not legal. |
| * It is recommended that the {@code mbeanServerName} |
| * be unique in the context of a JVM, and in the form of a java package |
| * identifier. If {@code mbeanServerName} is {@code null} then the created |
| * MBean Server has no name - and {@value #DEFAULT_MBEANSERVER_NAME} is used. |
| * Calling {@code createNamedMBeanServer(null,domain)} is equivalent |
| * to calling {@link #createMBeanServer(String) createMBeanServer(domain)}. |
| * |
| * @param domain the default domain name for the created |
| * MBeanServer. This is the value that will be returned by {@link |
| * MBeanServer#getDefaultDomain}. If a non null mbeanServerName is given, |
| * it is recommended to pass the same value as default domain. |
| * |
| * @return the newly created MBeanServer. |
| * |
| * @exception SecurityException if there is a SecurityManager and |
| * the caller's permissions do not include or imply <code>{@link |
| * MBeanServerPermission}("createMBeanServer")</code>. |
| * |
| * @exception JMRuntimeException if the property |
| * <code>javax.management.builder.initial</code> exists but the |
| * class it names cannot be instantiated through a public |
| * no-argument constructor; or if the instantiated builder returns |
| * null from its {@link MBeanServerBuilder#newMBeanServerDelegate |
| * newMBeanServerDelegate} or {@link |
| * MBeanServerBuilder#newMBeanServer newMBeanServer} methods. |
| * |
| * @exception ClassCastException if the property |
| * <code>javax.management.builder.initial</code> exists and can be |
| * instantiated but is not assignment compatible with {@link |
| * MBeanServerBuilder}. |
| * |
| * @exception IllegalArgumentException if the specified |
| * {@code mbeanServerName} is empty, or is {@code "-"}, or contains a |
| * character which is not legal. |
| * |
| * @exception UnsupportedOperationException if the specified |
| * {@code mbeanServerName} cannot be set. |
| * |
| * @since 1.7 |
| */ |
| public static MBeanServer createNamedMBeanServer(String mbeanServerName, |
| String domain) { |
| return createMBeanServer(mbeanServerName, domain); |
| } |
| |
| /** |
| * <p>Return a new object implementing the MBeanServer interface |
| * with a standard default domain name, without keeping an |
| * internal reference to this new object. The default domain name |
| * is used as the domain part in the ObjectName of MBeans when the |
| * domain is specified by the user is null.</p> |
| * |
| * <p>The standard default domain name is |
| * <code>DefaultDomain</code>.</p> |
| * |
| * <p>No reference is kept. <CODE>findMBeanServer</CODE> will not |
| * be able to return a reference to this MBeanServer object, but |
| * the garbage collector will be able to remove the MBeanServer |
| * object when it is no longer referenced.</p> |
| * |
| * <p>This method is equivalent to <code>newMBeanServer(null)</code>.</p> |
| * |
| * @return the newly created MBeanServer. |
| * |
| * @exception SecurityException if there is a SecurityManager and the |
| * caller's permissions do not include or imply <code>{@link |
| * MBeanServerPermission}("newMBeanServer")</code>. |
| * |
| * @exception JMRuntimeException if the property |
| * <code>javax.management.builder.initial</code> exists but the |
| * class it names cannot be instantiated through a public |
| * no-argument constructor; or if the instantiated builder returns |
| * null from its {@link MBeanServerBuilder#newMBeanServerDelegate |
| * newMBeanServerDelegate} or {@link |
| * MBeanServerBuilder#newMBeanServer newMBeanServer} methods. |
| * |
| * @exception ClassCastException if the property |
| * <code>javax.management.builder.initial</code> exists and can be |
| * instantiated but is not assignment compatible with {@link |
| * MBeanServerBuilder}. |
| */ |
| public static MBeanServer newMBeanServer() { |
| return newMBeanServer(null); |
| } |
| |
| /** |
| * <p>Return a new object implementing the MBeanServer interface |
| * with the specified default domain name, without keeping an |
| * internal reference to this new object. The given domain name |
| * is used as the domain part in the ObjectName of MBeans when the |
| * domain is specified by the user is null.</p> |
| * |
| * <p>No reference is kept. <CODE>findMBeanServer</CODE> will not |
| * be able to return a reference to this MBeanServer object, but |
| * the garbage collector will be able to remove the MBeanServer |
| * object when it is no longer referenced.</p> |
| * |
| * @param domain the default domain name for the created |
| * MBeanServer. This is the value that will be returned by {@link |
| * MBeanServer#getDefaultDomain}. |
| * |
| * @return the newly created MBeanServer. |
| * |
| * @exception SecurityException if there is a SecurityManager and the |
| * caller's permissions do not include or imply <code>{@link |
| * MBeanServerPermission}("newMBeanServer")</code>. |
| * |
| * @exception JMRuntimeException if the property |
| * <code>javax.management.builder.initial</code> exists but the |
| * class it names cannot be instantiated through a public |
| * no-argument constructor; or if the instantiated builder returns |
| * null from its {@link MBeanServerBuilder#newMBeanServerDelegate |
| * newMBeanServerDelegate} or {@link |
| * MBeanServerBuilder#newMBeanServer newMBeanServer} methods. |
| * |
| * @exception ClassCastException if the property |
| * <code>javax.management.builder.initial</code> exists and can be |
| * instantiated but is not assignment compatible with {@link |
| * MBeanServerBuilder}. |
| */ |
| public static MBeanServer newMBeanServer(String domain) { |
| return newMBeanServer(null,domain); |
| } |
| |
| /** |
| * <p>Return a new object implementing the MBeanServer interface |
| * with the specified <a href="#MBeanServerName">MBean server name</a> |
| * and default domain name, without keeping an |
| * internal reference to this new object. The given MBean server name |
| * is used in <a href="MBeanServer.html#security">security checks</a>. |
| * The given domain name |
| * is used as the domain part in the ObjectName of MBeans when the |
| * domain is specified by the user is null.</p> |
| * |
| * <p>No reference is kept. <CODE>findMBeanServer</CODE> and |
| * <CODE>findMBeanServerByName</CODE> will not |
| * be able to return a reference to this MBeanServer object, but |
| * the garbage collector will be able to remove the MBeanServer |
| * object when it is no longer referenced.</p> |
| * |
| * @param mbeanServerName the name for the created |
| * MBeanServer. This is the name that will be included in the |
| * {@linkplain MBeanPermission permission you need} when checking |
| * <a href="MBeanServer.html#security">MBean Permissions</a> for accessing |
| * an MBean registered in the returned MBeanServer. The characters |
| * {@code ':'} (colon), {@code ';'} (semicolon), {@code '*'} (star) |
| * and {@code '?'} are not legal. |
| * It is recommended that the mbeanServerName |
| * be unique in the context of a JVM, and in the form of a java package |
| * identifier. If {@code mbeanServerName} is {@code null} then the created |
| * MBean Server has no name - and {@value #DEFAULT_MBEANSERVER_NAME} is used. |
| * Calling {@code newNamedMBeanServer(null,domain)} is equivalent |
| * to calling {@link #newMBeanServer(String) newMBeanServer(domain)}. |
| * |
| * @param domain the default domain name for the created |
| * MBeanServer. This is the value that will be returned by {@link |
| * MBeanServer#getDefaultDomain}. |
| * |
| * @return the newly created MBeanServer. |
| * |
| * @exception SecurityException if there is a SecurityManager and the |
| * caller's permissions do not include or imply <code>{@link |
| * MBeanServerPermission}("newMBeanServer")</code>. |
| * |
| * @exception JMRuntimeException if the property |
| * <code>javax.management.builder.initial</code> exists but the |
| * class it names cannot be instantiated through a public |
| * no-argument constructor; or if the instantiated builder returns |
| * null from its {@link MBeanServerBuilder#newMBeanServerDelegate |
| * newMBeanServerDelegate} or {@link |
| * MBeanServerBuilder#newMBeanServer newMBeanServer} methods. |
| * |
| * @exception ClassCastException if the property |
| * <code>javax.management.builder.initial</code> exists and can be |
| * instantiated but is not assignment compatible with {@link |
| * MBeanServerBuilder}. |
| * |
| * @exception IllegalArgumentException if the specified |
| * {@code mbeanServerName} is empty, or is {@code "-"}, |
| * or contains a character which is not legal. |
| * |
| * @exception UnsupportedOperationException if the specified |
| * {@code mbeanServerName} cannot be set. |
| * |
| * @since 1.7 |
| */ |
| public static MBeanServer newNamedMBeanServer(String mbeanServerName, |
| String domain) { |
| return newMBeanServer(mbeanServerName, domain); |
| } |
| |
| private static MBeanServer createMBeanServer(String mbeanServerName, |
| String domain) { |
| checkPermission("createMBeanServer"); |
| |
| final MBeanServer mBeanServer = |
| newMBeanServer(mbeanServerName,domain); |
| addMBeanServer(mBeanServer); |
| return mBeanServer; |
| } |
| |
| private static MBeanServer newMBeanServer(String mbeanServerName, |
| String domain) { |
| checkPermission("newMBeanServer"); |
| |
| // Get the builder. Creates a new one if necessary. |
| // |
| final MBeanServerBuilder mbsBuilder = getNewMBeanServerBuilder(); |
| // Returned value cannot be null. NullPointerException if violated. |
| |
| synchronized(mbsBuilder) { |
| final MBeanServerDelegate delegate = |
| mbsBuilder.newMBeanServerDelegate(); |
| if (delegate == null) { |
| final String msg = |
| "MBeanServerBuilder.newMBeanServerDelegate() " + |
| "returned null"; |
| throw new JMRuntimeException(msg); |
| } |
| |
| // Sets the name on the delegate. For complex backward |
| // compatibility reasons it is not possible to give the |
| // name to the MBeanServerDelegate constructor. |
| // |
| // The method setMBeanServerName() will call getMBeanServerId() |
| // to check that the name is accurately set in the MBeanServerId. |
| // If not (which could happen if a custom MBeanServerDelegate |
| // implementation overrides getMBeanServerId() and was not updated |
| // with respect to JMX 2.0 spec, this method will throw an |
| // IllegalStateException... |
| // |
| if (!Util.isMBeanServerNameUndefined(mbeanServerName)) { |
| delegate.setMBeanServerName(mbeanServerName); |
| } |
| |
| final MBeanServer mbeanServer = |
| mbsBuilder.newMBeanServer(domain,null,delegate); |
| if (mbeanServer == null) { |
| final String msg = |
| "MBeanServerBuilder.newMBeanServer() returned null"; |
| throw new JMRuntimeException(msg); |
| } |
| |
| // double check that the MBeanServer name is correctly set. |
| // "*" might mean that the caller doesn't have the permission |
| // to see the MBeanServer name. |
| // |
| final String mbsName = Util.getMBeanServerSecurityName(mbeanServer); |
| if (!mbsName.equals(Util.checkServerName(mbeanServerName)) |
| && !mbsName.equals("*")) { |
| throw new UnsupportedOperationException( |
| "can't create MBeanServer with name \""+ |
| mbeanServerName+"\" using "+ |
| builder.getClass().getName()); |
| } |
| |
| return mbeanServer; |
| } |
| } |
| |
| /** |
| * <p>Return a list of registered MBeanServer objects. A |
| * registered MBeanServer object is one that was created by one of |
| * the <code>createMBeanServer</code> methods and not subsequently |
| * released with <code>releaseMBeanServer</code>.</p> |
| * |
| * @param agentId The agent identifier of the MBeanServer to |
| * retrieve. If this parameter is null, all registered |
| * MBeanServers in this JVM are returned. Otherwise, only |
| * MBeanServers whose id is equal to <code>agentId</code> are |
| * returned. The id of an MBeanServer is the |
| * <code>MBeanServerId</code> attribute of its delegate MBean. |
| * |
| * @return A list of MBeanServer objects. |
| * |
| * @exception SecurityException if there is a SecurityManager and the |
| * caller's permissions do not include or imply <code>{@link |
| * MBeanServerPermission}("findMBeanServer")</code>. |
| */ |
| public synchronized static |
| ArrayList<MBeanServer> findMBeanServer(String agentId) { |
| |
| checkPermission("findMBeanServer"); |
| |
| if (agentId == null) |
| return new ArrayList<MBeanServer>(mBeanServerList); |
| |
| ArrayList<MBeanServer> result = new ArrayList<MBeanServer>(); |
| for (MBeanServer mbs : mBeanServerList) { |
| String name = mBeanServerId(mbs); |
| if (agentId.equals(name)) |
| result.add(mbs); |
| } |
| return result; |
| } |
| |
| /** |
| * <p>Returns a list of registered MBeanServer objects with the given name. A |
| * registered MBeanServer object is one that was created by one of |
| * the <code>createMBeanServer</code> or <code>createNamedMBeanServer</code> |
| * methods and not subsequently released with <code>releaseMBeanServer</code>.</p> |
| * <p>See the section about <a href="#MBeanServerName">MBean Server names</a> |
| * above.</p> |
| * |
| * @param mbeanServerName The name of the MBeanServer to |
| * retrieve. If this parameter is null, all registered MBeanServers |
| * in this JVM are returned. |
| * Otherwise, only those MBeanServers that have a name |
| * matching <code>mbeanServerName</code> are returned: this |
| * parameter can be a pattern, where {@code '*'} matches any |
| * sequence of characters and {@code '?'} matches any character.<br> |
| * The name of an MBeanServer, if specified, is embedded in the |
| * <code>MBeanServerId</code> attribute of its delegate MBean: |
| * this method will parse the <code>MBeanServerId</code> to get the |
| * MBeanServer name. If this parameter is equal to {@code "*"} then |
| * all registered MBeanServers in this JVM are returned, whether they have |
| * a name or not: {@code findMBeanServerByName(null)}, |
| * {@code findMBeanServerByName("*")} and {@code findMBeanServer(null)}, |
| * are equivalent. It is also possible to get all MBeanServers for which |
| * no name was specified by calling <code>findMBeanServerByName({@value |
| * #DEFAULT_MBEANSERVER_NAME})</code>. |
| * |
| * @return A list of MBeanServer objects. |
| * |
| * @exception SecurityException if there is a SecurityManager and the |
| * caller's permissions do not include or imply <code>{@link |
| * MBeanServerPermission}("findMBeanServer")</code>. |
| * |
| * @see #getMBeanServerName(MBeanServer) |
| * @since 1.7 |
| */ |
| public synchronized static |
| List<MBeanServer> findMBeanServerByName(String mbeanServerName) { |
| |
| checkPermission("findMBeanServer"); |
| |
| if (mbeanServerName==null || "*".equals(mbeanServerName)) |
| return new ArrayList<MBeanServer>(mBeanServerList); |
| |
| // noname=true iff we are looking for MBeanServers for which no name |
| // were specified. |
| ArrayList<MBeanServer> result = new ArrayList<MBeanServer>(); |
| for (MBeanServer mbs : mBeanServerList) { |
| final String name = Util.getMBeanServerSecurityName(mbs); |
| if (Util.wildmatch(name, mbeanServerName)) result.add(mbs); |
| } |
| return result; |
| } |
| |
| /** |
| * Returns the name of the MBeanServer embedded in the MBeanServerId of |
| * the given {@code server}. If the given MBeanServerId doesn't contain |
| * any name, {@value #DEFAULT_MBEANSERVER_NAME} is returned. |
| * The MBeanServerId is expected to be of the form: |
| * {@code *[;mbeanServerName=<mbeanServerName>[;*]]} |
| * <br>where {@code *} denotes any sequence of characters, and {@code [ ]} |
| * indicate optional parts. |
| * </p> |
| * <p>For instance, if an MBeanServer is created using {@link |
| * #createNamedMBeanServer(java.lang.String, java.lang.String) |
| * server = |
| * MBeanServerFactory.createNamedMBeanServer("com.mycompany.myapp.server1", |
| * null)} then {@code MBeanServerFactory.getMBeanServerName(server)} |
| * will return {@code "com.mycompany.myapp.server1"} and |
| * <code>server.getAttribute({@link |
| * javax.management.MBeanServerDelegate#DELEGATE_NAME |
| * MBeanServerDelegate.DELEGATE_NAME}, "MBeanServerId")</code> will return |
| * something like |
| * {@code "myhost_1213353064145;mbeanServerName=com.mycompany.myapp.server1"}. |
| * </p> |
| * <p>See the section about <a href="#MBeanServerName">MBean Server names</a> |
| * above.</p> |
| * @param server A named (or unnamed) MBeanServer. |
| * @return the name of the MBeanServer if found, or |
| * {@value #DEFAULT_MBEANSERVER_NAME} if no name is |
| * present in its MBeanServerId, or "*" if its |
| * MBeanServerId couldn't be obtained. Returning "*" means that |
| * only {@link MBeanPermission}s that allow all MBean Server names |
| * will apply to this MBean Server. |
| * @see MBeanServerDelegate |
| * @since 1.7 |
| */ |
| public static String getMBeanServerName(MBeanServer server) { |
| return Util.getMBeanServerSecurityName(server); |
| } |
| |
| /** |
| * Return the ClassLoaderRepository used by the given MBeanServer. |
| * This method is equivalent to {@link |
| * MBeanServer#getClassLoaderRepository() server.getClassLoaderRepository()}. |
| * @param server The MBeanServer under examination. Since JMX 1.2, |
| * if <code>server</code> is <code>null</code>, the result is a |
| * {@link NullPointerException}. This behavior differs from what |
| * was implemented in JMX 1.1 - where the possibility to use |
| * <code>null</code> was deprecated. |
| * @return The Class Loader Repository used by the given MBeanServer. |
| * @exception SecurityException if there is a SecurityManager and |
| * the caller's permissions do not include or imply <code>{@link |
| * MBeanPermission}("getClassLoaderRepository")</code>. |
| * |
| * @exception NullPointerException if <code>server</code> is null. |
| * |
| **/ |
| public static ClassLoaderRepository getClassLoaderRepository( |
| MBeanServer server) { |
| return server.getClassLoaderRepository(); |
| } |
| |
| private static String mBeanServerId(MBeanServer mbs) { |
| try { |
| return (String) mbs.getAttribute(MBeanServerDelegate.DELEGATE_NAME, |
| "MBeanServerId"); |
| } catch (JMException e) { |
| JmxProperties.MISC_LOGGER.finest( |
| "Ignoring exception while getting MBeanServerId: "+e); |
| return null; |
| } |
| } |
| |
| private static void checkPermission(String action) |
| throws SecurityException { |
| SecurityManager sm = System.getSecurityManager(); |
| if (sm != null) { |
| Permission perm = new MBeanServerPermission(action); |
| sm.checkPermission(perm); |
| } |
| } |
| |
| private static synchronized void addMBeanServer(MBeanServer mbs) { |
| mBeanServerList.add(mbs); |
| } |
| |
| private static synchronized void removeMBeanServer(MBeanServer mbs) { |
| boolean removed = mBeanServerList.remove(mbs); |
| if (!removed) { |
| MBEANSERVER_LOGGER.logp(Level.FINER, |
| MBeanServerFactory.class.getName(), |
| "removeMBeanServer(MBeanServer)", |
| "MBeanServer was not in list!"); |
| throw new IllegalArgumentException("MBeanServer was not in list!"); |
| } |
| } |
| |
| private static final ArrayList<MBeanServer> mBeanServerList = |
| new ArrayList<MBeanServer>(); |
| |
| /** |
| * Load the builder class through the context class loader. |
| * @param builderClassName The name of the builder class. |
| **/ |
| private static Class loadBuilderClass(String builderClassName) |
| throws ClassNotFoundException { |
| final ClassLoader loader = |
| Thread.currentThread().getContextClassLoader(); |
| |
| if (loader != null) { |
| // Try with context class loader |
| return loader.loadClass(builderClassName); |
| } |
| |
| // No context class loader? Try with Class.forName() |
| return Class.forName(builderClassName); |
| } |
| |
| /** |
| * Creates the initial builder according to the |
| * javax.management.builder.initial System property - if specified. |
| * If any checked exception needs to be thrown, it is embedded in |
| * a JMRuntimeException. |
| **/ |
| private static MBeanServerBuilder newBuilder(Class builderClass) { |
| try { |
| final Object abuilder = builderClass.newInstance(); |
| return (MBeanServerBuilder)abuilder; |
| } catch (RuntimeException x) { |
| throw x; |
| } catch (Exception x) { |
| final String msg = |
| "Failed to instantiate a MBeanServerBuilder from " + |
| builderClass + ": " + x; |
| throw new JMRuntimeException(msg, x); |
| } |
| } |
| |
| /** |
| * Instantiate a new builder according to the |
| * javax.management.builder.initial System property - if needed. |
| **/ |
| private static synchronized void checkMBeanServerBuilder() { |
| try { |
| GetPropertyAction act = |
| new GetPropertyAction(JMX_INITIAL_BUILDER); |
| String builderClassName = AccessController.doPrivileged(act); |
| |
| try { |
| final Class newBuilderClass; |
| if (builderClassName == null || builderClassName.length() == 0) |
| newBuilderClass = MBeanServerBuilder.class; |
| else |
| newBuilderClass = loadBuilderClass(builderClassName); |
| |
| // Check whether a new builder needs to be created |
| if (builder != null) { |
| final Class builderClass = builder.getClass(); |
| if (newBuilderClass == builderClass) |
| return; // no need to create a new builder... |
| } |
| |
| // Create a new builder |
| builder = newBuilder(newBuilderClass); |
| } catch (ClassNotFoundException x) { |
| final String msg = |
| "Failed to load MBeanServerBuilder class " + |
| builderClassName + ": " + x; |
| throw new JMRuntimeException(msg, x); |
| } |
| } catch (RuntimeException x) { |
| if (MBEANSERVER_LOGGER.isLoggable(Level.FINEST)) { |
| StringBuilder strb = new StringBuilder() |
| .append("Failed to instantiate MBeanServerBuilder: ").append(x) |
| .append("\n\t\tCheck the value of the ") |
| .append(JMX_INITIAL_BUILDER).append(" property."); |
| MBEANSERVER_LOGGER.logp(Level.FINEST, |
| MBeanServerFactory.class.getName(), |
| "checkMBeanServerBuilder", |
| strb.toString()); |
| } |
| throw x; |
| } |
| } |
| |
| /** |
| * Get the current {@link javax.management.MBeanServerBuilder}, |
| * as specified by the current value of the |
| * javax.management.builder.initial property. |
| * |
| * This method consults the property and instantiates a new builder |
| * if needed. |
| * |
| * @return the new current {@link javax.management.MBeanServerBuilder}. |
| * |
| * @exception SecurityException if there is a SecurityManager and |
| * the caller's permissions do not make it possible to instantiate |
| * a new builder. |
| * @exception JMRuntimeException if the builder instantiation |
| * fails with a checked exception - |
| * {@link java.lang.ClassNotFoundException} etc... |
| * |
| **/ |
| private static synchronized MBeanServerBuilder getNewMBeanServerBuilder() { |
| checkMBeanServerBuilder(); |
| return builder; |
| } |
| |
| } |