/* * Copyright 1999-2008 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; /** *
Provides MBean server references. There are no instances of * this class.
* *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 * javax.management.builder.initial system property. * The specified class must be a public subclass of * {@link javax.management.MBeanServerBuilder}, and must have a public * empty constructor. *
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.
* *The javax.management.builder.initial 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.
* *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 javax.management.builder.initial system property is reset to * valid value.
* *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.
* *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:
*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.
*The name of the MBeanServer is particularly useful when * MBean permissions 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".
*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.
* * @since 1.5 */ public class MBeanServerFactory { /** * The MBean Server name that will be * checked by a permission you need * 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{@link
* MBeanServerPermission}("setMBeanServerBuilder")
.
*
**/
// 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 {@link
* MBeanServerPermission}("getMBeanServerBuilder")
.
*
**/
// 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
* mbeanServer
was not generated by one of the
* createMBeanServer
methods, or if
* releaseMBeanServer
was already called on it.
*
* @exception SecurityException if there is a SecurityManager and
* the caller's permissions do not include or imply {@link
* MBeanServerPermission}("releaseMBeanServer")
.
*/
public static void releaseMBeanServer(MBeanServer mbeanServer) {
checkPermission("releaseMBeanServer");
removeMBeanServer(mbeanServer);
}
/**
* 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.
* *The standard default domain name is
* DefaultDomain
.
The MBeanServer reference is internally kept. This will
* allow findMBeanServer
to return a reference to
* this MBeanServer object.
This method is equivalent to createMBeanServer(null)
.
*
* @return the newly created MBeanServer.
*
* @exception SecurityException if there is a SecurityManager and the
* caller's permissions do not include or imply {@link
* MBeanServerPermission}("createMBeanServer")
.
*
* @exception JMRuntimeException if the property
* javax.management.builder.initial
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
* javax.management.builder.initial
exists and can be
* instantiated but is not assignment compatible with {@link
* MBeanServerBuilder}.
*/
public static MBeanServer createMBeanServer() {
return createMBeanServer(null);
}
/**
*
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.
* *The MBeanServer reference is internally kept. This will
* allow findMBeanServer
to return a reference to
* this MBeanServer object.
{@link
* MBeanServerPermission}("createMBeanServer")
.
*
* @exception JMRuntimeException if the property
* javax.management.builder.initial
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
* javax.management.builder.initial
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);
}
/**
* Return a new object implementing the {@link MBeanServer} * interface with the specified * MBean Server name * and default domain name. The given MBean server name * is used in security checks, 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.
* *The MBeanServer reference is internally kept. This will
* allow findMBeanServer
to return a reference to
* this MBeanServer object.
{@link
* MBeanServerPermission}("createMBeanServer")
.
*
* @exception JMRuntimeException if the property
* javax.management.builder.initial
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
* javax.management.builder.initial
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);
}
/**
* 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.
* *The standard default domain name is
* DefaultDomain
.
No reference is kept. findMBeanServer
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.
This method is equivalent to newMBeanServer(null)
.
{@link
* MBeanServerPermission}("newMBeanServer")
.
*
* @exception JMRuntimeException if the property
* javax.management.builder.initial
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
* javax.management.builder.initial
exists and can be
* instantiated but is not assignment compatible with {@link
* MBeanServerBuilder}.
*/
public static MBeanServer newMBeanServer() {
return newMBeanServer(null);
}
/**
* 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.
* *No reference is kept. findMBeanServer
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.
{@link
* MBeanServerPermission}("newMBeanServer")
.
*
* @exception JMRuntimeException if the property
* javax.management.builder.initial
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
* javax.management.builder.initial
exists and can be
* instantiated but is not assignment compatible with {@link
* MBeanServerBuilder}.
*/
public static MBeanServer newMBeanServer(String domain) {
return newMBeanServer(null,domain);
}
/**
* Return a new object implementing the MBeanServer interface * with the specified MBean server name * and default domain name, without keeping an * internal reference to this new object. The given MBean server name * is used in security checks. * 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.
* *No reference is kept. findMBeanServer
and
* findMBeanServerByName
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.
{@link
* MBeanServerPermission}("newMBeanServer")
.
*
* @exception JMRuntimeException if the property
* javax.management.builder.initial
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
* javax.management.builder.initial
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;
}
}
/**
* Return a list of registered MBeanServer objects. A
* registered MBeanServer object is one that was created by one of
* the createMBeanServer
methods and not subsequently
* released with releaseMBeanServer
.
agentId
are
* returned. The id of an MBeanServer is the
* MBeanServerId
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 {@link
* MBeanServerPermission}("findMBeanServer")
.
*/
public synchronized static
ArrayListReturns a list of registered MBeanServer objects with the given name. A
* registered MBeanServer object is one that was created by one of
* the createMBeanServer
or createNamedMBeanServer
* methods and not subsequently released with releaseMBeanServer
.
See the section about MBean Server names * above.
* * @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 * matchingmbeanServerName
are returned: this
* parameter can be a pattern, where {@code '*'} matches any
* sequence of characters and {@code '?'} matches any character.MBeanServerId
attribute of its delegate MBean:
* this method will parse the MBeanServerId
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 findMBeanServerByName({@value
* #DEFAULT_MBEANSERVER_NAME})
.
*
* @return A list of MBeanServer objects.
*
* @exception SecurityException if there is a SecurityManager and the
* caller's permissions do not include or imply {@link
* MBeanServerPermission}("findMBeanServer")
.
*
* @see #getMBeanServerName(MBeanServer)
* @since 1.7
*/
public synchronized static
ListFor 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
* server.getAttribute({@link
* javax.management.MBeanServerDelegate#DELEGATE_NAME
* MBeanServerDelegate.DELEGATE_NAME}, "MBeanServerId")
will return
* something like
* {@code "myhost_1213353064145;mbeanServerName=com.mycompany.myapp.server1"}.
*
See the section about MBean Server names * above.
* @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, * ifserver
is null
, the result is a
* {@link NullPointerException}. This behavior differs from what
* was implemented in JMX 1.1 - where the possibility to use
* null
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 {@link
* MBeanPermission}("getClassLoaderRepository")
.
*
* @exception NullPointerException if server
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