6745832: jmx namespaces: Some refactoring/commenting would improve code readability.
Reviewed-by: emcmanus
/*
* Copyright 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.namespace;
import java.io.IOException;
import java.util.UUID;
import javax.management.MBeanRegistration;
import javax.management.MBeanServer;
import javax.management.ObjectName;
/**
* MBean Servers can be federated into a single hierarchical name space:
* A JMXNamespace is an MBean that handles a sub name space in that
* hierarchical name space.
* <p>
* A name space is created simply by registering a {@code JMXNamespace}
* MBean in the MBean Server. The name of the created name space is defined
* by the {@linkplain JMXNamespaces#getNamespaceObjectName name of the JMXNamespace}
* that handles it. A name space is equivalent to
* an MBean Server within an MBean Server. When creating a {@code JMXNamespace},
* the MBean Server within is passed to the constructor.
* </p>
* <p>
* The {@code JMXNamespace} class is the base class for implementing
* all name space handlers. All name space handlers must be instances of
* {@code JMXNamespace} or a subclass of it.
* </p>
* <p>
* A concrete example of a {@code JMXNamespace} MBean subclass
* is the {@link JMXRemoteNamespace JMXRemoteNamespace} MBean which
* is able to mirror all MBeans contained in a remote MBean server known by its
* {@link javax.management.remote.JMXServiceURL}.
* </p>
* <p>
* You can create a local namespace by supplying a newly created MBean Server
* to an instance of {@code JMXNamespace}. For instance:
* <pre>
* final String namespace = "foo";
* final ObjectName namespaceName = {@link JMXNamespaces#getNamespaceObjectName
* JMXNamespaces.getNamespaceObjectName(namespace)};
* server.registerMBean(new JMXNamespace(MBeanServerFactory.newMBeanServer()),
* namespaceName);
* </pre>
* </p>
* <p>
* <u>Note:</u> A JMXNamespace MBean cannot be registered
* simultaneously in two different
* MBean servers, or indeed in the same MBean Server with two
* different names. It is however possible to give the same MBeanServer
* instance to two different JMXNamespace MBeans, and thus create a graph
* rather than a tree.
* </p>
*
* <p>To view the content of a namespace, you will usually use an
* instance of {@link JMXNamespaceView}. For instance, given the
* namespace {@code "foo"} created above, you would do:
* </p>
* <pre>
* final JMXNamespaceView view = new JMXNamespaceView(server);
* System.out.println("List of namespaces: "+Arrays.toString({@link JMXNamespaceView#list() view.list()}));
*
* final JMXNamespaceView foo = {@link JMXNamespaceView#down view.down("foo")};
* System.out.println({@link JMXNamespaceView#where() foo.where()}+" contains: " +
* {@link JMXNamespaceView#getMBeanServerConnection foo.getMBeanServerConnection()}.queryNames(null,null));
* </pre>
*
* <h2 id="PermissionChecks">JMX Namespace Permission Checks</h2>
*
* <p>A special {@link JMXNamespacePermission} is defined to check access
* to MBean within namespaces.</p>
* <p>When a JMXNamespace MBean is registered in an
* MBean server created through the default {@link
* javax.management.MBeanServerBuilder}, and if a {@link
* SecurityManager SecurityManager} is
* {@linkplain System#getSecurityManager() present}, the MBeanServer will
* check a {@link JMXNamespacePermission} before invoking
* any method on the {@linkplain #getSourceServer source MBeanServer} of the
* JMXNamespace.
* {@linkplain JMXNamespacePermission JMX Namespace Permissions} are similar to
* {@linkplain javax.management.MBeanPermission MBean Permissions}, except
* that you usually cannot specify an MBean class name. You can however
* specify object name patterns - which will allow you for example to only grant
* permissions for MBeans having a specific {@code type=<MBeanType>} key
* in their object name.
* <p>
* Another difference is that {@link JMXNamespacePermission
* JMXNamespacePermission} also specifies from which namespace and which
* MBean server the permission is granted.
* </p>
* <p>In the rest of this document, the following terms are used:</p>
* <ul>
* <li id="MBeanServerName"><p>{@code server name} is the
* <a href="../MBeanServerFactory.html#MBeanServerName">name of the
* MBeanServer</a> in which the permission is granted.
* The name of an {@code MBeanServer} can be obtained by calling {@link
* javax.management.MBeanServerFactory#getMBeanServerName
* MBeanServerFactory.getMBeanServerName(mbeanServer)}
* </p>
* <li id="NamespaceName"><p>{@code namespace} is the name of the namespace
* in the <a href="#MBeanServerName">named MBean server</a> for which the
* permission is granted. It doesn't contain any
* {@link JMXNamespaces#NAMESPACE_SEPARATOR namespace separator}.
* </p>
* <li id="MBeanName"><p>{@code mbean} is the name
* of the MBean in that {@code namespace}. This is the name of the MBean
* in the namespace's {@link JMXNamespace#getSourceServer() source mbean server}.
* It might contain no, one, or several {@link
* JMXNamespaces#NAMESPACE_SEPARATOR namespace separators}.
* </p>
* </ul>
*
* <p>For instance let's assume that some piece of code calls:</p>
* <pre>
* final MBeanServer mbeanServer = ...;
* final ObjectName name = new ObjectName("a//b//c//D:k=v");
* mbeanServer.getAttribute(name,"Foo");
* </pre>
* <p>
* Assuming that there is a security manager, or that the
* implementation chooses to make checks anyway, the checks that will
* be made in that case are:
* </p>
* <ol>
* <li id="check1">
* <code>JMXNamespacePermission(mbeanServerName, "Foo", "<b>a//</b>b//c//D:k=v",
* "getAttribute")</code>
* (where {@code mbeanServerName=MBeanServerFactory.getMBeanServerName(mbeanServer)},
* <code>namespace="<b>a</b>"</code>, and {@code mbean="b//c//D:k=v"})
* </li>
* <li id="check2">and in addition if namespace {@code "a"} is local,
* <code>JMXNamespacePermission(aSourceServerName,"Foo","<b>b//</b>c//D:k=v",
* "getAttribute")}</code>
* (where
* {@code aSourceServerName=MBeanServerFactory.getMBeanServerName(sourceServer(a))},
* <code>namespace="<b>b</b>"</code>, and {@code mbean="c//D:k=v"}),
* </li>
* <li id="check3">and in addition if namespace {@code "b"} is also local,
* <code>JMXNamespacePermission(bSourceServerName,"Foo","<b>c//</b>D:k=v",
* "getAttribute")}</code>
* (where
* {@code bSourceServerName=MBeanServerFactory.getMBeanServerName(sourceServer(b))},
* <code>namespace="<b>c</b>"</code>, and {@code mbean="D:k=v"}),
* </li>
* <li id="check4">and in addition if the source mbean server of namespace
* {@code "c"} is a also a local MBeanServer in this JVM,
* {@code MBeanPermission(cSourceServerName,<className(D:k=v)>,"Foo","D:k=v","getAttrinute")},
* (where
* {@code cSourceServerName=MBeanServerFactory.getMBeanServerName(sourceServer(c))}).
* </li>
* </ol>
* <p>For any of these MBean servers, if no name was supplied when
* creating that MBeanServer the {@link JMXNamespacePermission} is
* created with an {@code mbeanServerName} equal to
* {@value javax.management.MBeanServerFactory#DEFAULT_MBEANSERVER_NAME}.
* </p>
* <p>If the namespace {@code a} is in fact a remote {@code MBeanServer},
* for instance because namespace {@code a} is implemented by a {@link
* JMXRemoteNamespace} pointing to a distant MBeanServer located in
* another JMX agent, then checks <a href="#check2">2</a>,
* <a href="#check3">3</a>, and <a href="#check4">4</a> will not
* be performed in the local JVM. They might or might not be performed in
* the remote agent, depending on how access control and permission
* checking are configured in the remote agent, and how authentication
* is configured in the connector used by the {@link
* JMXRemoteNamespace}.
* </p>
* <p>In all cases, {@linkplain JMXNamespacePermission JMX Namespace Permissions}
* are checked as follows:</p>
* <p>First, if there is no security manager ({@link
* System#getSecurityManager()} is null), then an implementation of
* of MBeanServer that supports JMX namespaces is free not to make any
* checks.</p>
*
* <p>Assuming that there is a security manager, or that the
* implementation chooses to make checks anyway, the checks are made
* as detailed below.</p>
*
* <p>If a security check fails, the method throws {@link
* SecurityException}.</p>
*
* <ul>
*
* <li><p>For the {@link MBeanServer#invoke invoke} method, the caller's
* permissions must imply {@link
* JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
* JMXNamespacePermission(<mbean server name>, <operation name>, <namespace>//<mbean>, "invoke")},
* where <a href="#MBeanServerName">mbean server name</a> is the name of the
* {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
* <a href="#NamespaceName">namespace</a> is registered, and
* <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
* is performed, in that namespace.
* </p>
*
* <li><p>For the {@link MBeanServer#getAttribute getAttribute} method, the
* caller's permissions must imply {@link
* JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
* JMXNamespacePermission(<mbean server name>, <attribute>, <namespace>//<mbean>, "getAttribute")}.
* </p>
*
* <li><p>For the {@link MBeanServer#getAttributes getAttributes} method, the
* caller's permissions must imply {@link
* JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
* JMXNamespacePermission(<mbean server name>, <null>, <namespace>//<mbean>, "getAttribute")},
* where <a href="#MBeanServerName">mbean server name</a> is the name of the
* {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
* <a href="#NamespaceName">namespace</a> is registered, and
* <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
* is performed, in that namespace.
* Additionally, for each attribute <em>att</em> in the {@link
* javax.management.AttributeList}, if the caller's permissions do not
* imply {@link
* JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
* JMXNamespacePermission(<mbean server name>, <em>att</em>,
* <namespace>//<mbean>, "getAttribute")}, the
* MBean server will behave as if that attribute had not been in the
* supplied list.</p>
*
* <li><p>For the {@link MBeanServer#setAttribute setAttribute} method, the
* caller's permissions must imply {@link
* JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
* JMXNamespacePermission(<mbean server name>, <attrName>, <namespace>//<mbean>, "setAttribute")},
* where <a href="#MBeanServerName">mbean server name</a> is the name of the
* {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
* <a href="#NamespaceName">namespace</a> is registered, and
* <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
* is performed, in that namespace, and
* <code>attrName</code> is {@link javax.management.Attribute#getName()
* attribute.getName()}.</p>
*
* <li><p>For the {@link MBeanServer#setAttributes setAttributes} method, the
* caller's permissions must imply {@link
* JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
* JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>, "setAttribute")},
* where <a href="#MBeanServerName">mbean server name</a> is the name of the
* {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
* <a href="#NamespaceName">namespace</a> is registered, and
* <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
* is performed, in that namespace.
* Additionally, for each attribute <em>att</em> in the {@link
* javax.management.AttributeList}, if the caller's permissions do not
* imply {@link
* JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
* JMXNamespacePermission(<mbean server name>, <em>att</em>, <namespace>//<mbean>, "setAttribute")},
* the MBean server will behave as if that attribute had not been in the
* supplied list.</p>
*
* <li><p>For the <code>addNotificationListener</code> methods,
* the caller's permissions must imply {@link
* JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
* JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>,
* "addNotificationListener")},
* where <a href="#MBeanServerName">mbean server name</a> is the name of the
* {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
* <a href="#NamespaceName">namespace</a> is registered, and
* <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
* is performed, in that namespace.
* </p>
*
* <li><p>For the <code>removeNotificationListener</code> methods,
* the caller's permissions must imply {@link
* JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
* JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>,
* "removeNotificationListener")},
* where <a href="#MBeanServerName">mbean server name</a> is the name of the
* {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
* <a href="#NamespaceName">namespace</a> is registered, and
* <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
* is performed, in that namespace.
* </p>
*
* <li><p>For the {@link MBeanServer#getMBeanInfo getMBeanInfo} method, the
* caller's permissions must imply {@link
* JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
* JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>,
* "getMBeanInfo")},
* where <a href="#MBeanServerName">mbean server name</a> is the name of the
* {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
* <a href="#NamespaceName">namespace</a> is registered, and
* <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
* is performed, in that namespace.
* </p>
*
* <li><p>For the {@link MBeanServer#getObjectInstance getObjectInstance} method,
* the caller's permissions must imply {@link
* JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
* JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>,
* "getObjectInstance")},
* where <a href="#MBeanServerName">mbean server name/a> is the name of the
* {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
* <a href="#NamespaceName">namespace</a> is registered, and
* <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
* is performed, in that namespace.
* </p>
*
* <li><p>For the {@link MBeanServer#isInstanceOf isInstanceOf} method, the
* caller's permissions must imply {@link
* JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
* JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>,
* "isInstanceOf")},
* where <a href="#MBeanServerName">mbean server name</a> is the name of the
* {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
* <a href="#NamespaceName">namespace</a> is registered, and
* <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
* is performed, in that namespace.
* </p>
*
* <li><p>For the {@link MBeanServer#queryMBeans queryMBeans} method, the
* caller's permissions must imply {@link
* JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
* JMXNamespacePermission(<mbean server name>, null, null,
* "queryMBeans")}.
* Additionally, for each MBean {@code mbean} that matches {@code pattern},
* if the caller's permissions do not imply {@link
* JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
* JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>,
* "queryMBeans")}, the
* MBean server will behave as if that MBean did not exist.</p>
*
* <p>Certain query elements perform operations on the MBean server.
* However these operations are usually performed by the MBeanServer at the
* bottom of the namespace path, and therefore, do not involve any
* {@link JMXNamespacePermission} permission check. They might involve
* {@link javax.management.MBeanPermission} checks depending on how security
* in the JVM in which the bottom MBeanServer resides is implemented.
* See {@link javax.management.MBeanServer} for more details.
* </p>
*
* <li><p>For the {@link MBeanServer#queryNames queryNames} method, the checks
* are the same as for <code>queryMBeans</code> except that
* <code>"queryNames"</code> is used instead of
* <code>"queryMBeans"</code> in the <code>JMXNamespacePermission</code>
* objects. Note that a <code>"queryMBeans"</code> permission implies
* the corresponding <code>"queryNames"</code> permission.</p>
*
* <li><p>For the {@link MBeanServer#getClassLoader getClassLoader} method, the
* caller's permissions must imply {@link
* JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
* JMXNamespacePermission(<mbean server name>, null, <namespace>//<loaderName>,
* "getClassLoader")},
* where <a href="#MBeanServerName">mbean server name/a> is the name of the
* {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
* <a href="#NamespaceName">namespace</a> is registered, and
* <a href="#MBeanName">loaderName</a> is the name of the ClassLoader MBean
* which is accessed, in that namespace.
* </p>
*
* <li><p>For the {@link MBeanServer#getClassLoaderFor getClassLoaderFor} method,
* the caller's permissions must imply {@link
* JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
* JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>,
* "getClassLoaderFor")},
* where <a href="#MBeanServerName">mbean server name</a> is the name of the
* {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
* <a href="#NamespaceName">namespace</a> is registered, and
* <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
* is performed, in that namespace.
* </p>
*
* <li><p>For the {@link MBeanServer#registerMBean registerMBean} method, the
* caller's permissions must imply {@link
* JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
* JMXNamespacePermission(<mbean server name>, <class name>, <namespace>//<mbean>,
* "registerMBean")}. Here
* <code>class name</code> is the string returned by {@code
* obj.getClass().getName()} where {@code obj} is the mbean reference,
* <a href="#MBeanServerName"mbean server name/a> is the name of the
* {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
* <a href="#NamespaceName">namespace</a> is registered, and
* <a href="#MBeanName">mbean</a> is the name of the MBean which is being
* registered, relative to that namespace.
*
* <li><p>For the <code>createMBean</code> methods, the caller's
* permissions must imply {@link
* JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
* JMXNamespacePermission(<mbean server name>, <class name>, <namespace>//<mbean>,
* "instantiate")} and
* JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
* JMXNamespacePermission(<mbean server name>, <class name>, <namespace>//<mbean>,
* "registerMBean")}, where
* <code>class name</code> is the string passed as first argument to the {@code
* createMBean} method,
* <a href="#MBeanServerName">mbean server name</a> is the name of the
* {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
* <a href="#NamespaceName">namespace</a> is registered, and
* <a href="#MBeanName">mbean</a> is the name of the MBean which is being
* created, relative to that namespace.
*
* <li><p>For the {@link MBeanServer#unregisterMBean unregisterMBean} method,
* the caller's permissions must imply {@link
* JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
* JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>,
* "unregisterMBean")},
* where <a href="#MBeanServerName">mbean server name</a> is the name of the
* {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
* <a href="#NamespaceName">namespace</a> is registered, and
* <a href="#MBeanName">mbean</a> is the name of the MBean on which is
* being unregistered, relative to that namespace.
* </p>
* </ul>
* </p>
* <p>It must be noted that if all namespaces are local, and all
* local namespaces are implemented by regular MBean servers, that is, there
* are no {@linkplain MBeanServerSupport Virtual Namespaces}, then
* simple {@linkplain javax.management.MBeanPermission MBean Permission}
* checks might be enough to secure an application.
* In that case, it is possible to specify the following {@link
* JMXNamespacePermission} permission in the policy file, which implies all
* other JMX namespace permissions:
* </p>
* <pre>
* permission javax.management.namespace.JMXNamespacePermission "*::*[]", "*";
* </pre>
*
* @since 1.7
*/
public class JMXNamespace
implements JMXNamespaceMBean, MBeanRegistration {
/**
* The standard value of the {@code type}
* property key that must be used to construct valid {@link
* JMXNamespaceMBean} ObjectNames.<br>
* This is {@value #TYPE}.
**/
public static final String TYPE = "JMXNamespace";
/**
* The {@link ObjectName#getKeyPropertyListString keyPropertyListString}
* that must be used to construct valid {@link JMXNamespaceMBean}
* ObjectNames.<br>
* This is
* <code>{@value #TYPE_ASSIGNMENT}</code>.
**/
public static final String TYPE_ASSIGNMENT = "type="+TYPE;
private volatile MBeanServer mbeanServer; // the mbean server in which
// this MBean is registered.
private volatile ObjectName objectName; // the ObjectName of this MBean.
private final MBeanServer sourceServer; // the MBeanServer within = the
// name space (or the MBean server
// that contains it).
private final String uuid;
/**
* Creates a new JMXNamespace implemented by means of an MBean Server.
* A namespace is equivalent to an MBeanServer within an MBean Server.
* The {@code sourceServer} provided to this constructor is the MBean Server
* within.
* @param sourceServer the MBean server that implemented by this namespace.
* @see #getSourceServer
*/
public JMXNamespace(MBeanServer sourceServer) {
this.sourceServer = sourceServer;
this.uuid = UUID.randomUUID().toString();
}
/**
* This method is part of the {@link MBeanRegistration} interface.
* The {@link JMXNamespace} class uses the {@link MBeanRegistration}
* interface in order to get a reference to the MBean server in which it is
* registered. It also checks the validity of its own ObjectName.
* <p>
* This method is called by the MBean server.
* Application classes should never call this method directly.
* <p>
* If this method is overridden, the overriding method should call
* {@code super.preRegister(server,name)}.
* @see MBeanRegistration#preRegister MBeanRegistration
* @see JMXNamespaces#getNamespaceObjectName getNamespaceObjectName
* @param name The object name of the MBean. <var>name</var> must be a
* syntactically valid JMXNamespace name, as returned by
* {@link JMXNamespaces#getNamespaceObjectName(java.lang.String)
* getNamespaceObjectName(namespace)}.
* @return The name under which the MBean is to be registered.
* @throws IllegalArgumentException if the name supplied is not valid.
* @throws Exception can be thrown by subclasses.
*/
public ObjectName preRegister(MBeanServer server, ObjectName name)
throws Exception {
// need to synchronize to protect against multiple registration.
synchronized(this) {
if (objectName != null && ! objectName.equals(name))
throw new IllegalStateException(
"Already registered under another name: " + objectName);
objectName = validateHandlerName(name);
mbeanServer = server;
}
return name;
}
/**
* Validate the ObjectName supplied to preRegister.
* This method is introduced to allow standard subclasses to use
* an alternate naming scheme. For instance - if we want to
* reuse JMXNamespace in order to implement sessions...
* It is however only available for subclasses in this package.
**/
ObjectName validateHandlerName(ObjectName suppliedName) {
if (suppliedName == null)
throw new IllegalArgumentException("Must supply a valid name");
final String dirName = JMXNamespaces.
normalizeNamespaceName(suppliedName.getDomain());
final ObjectName handlerName =
JMXNamespaces.getNamespaceObjectName(dirName);
if (!suppliedName.equals(handlerName))
throw new IllegalArgumentException("invalid name space name: "+
suppliedName);
return suppliedName;
}
/**
* This method is part of the {@link MBeanRegistration} interface.
* The {@link JMXNamespace} class uses the {@link MBeanRegistration}
* interface in order to get a reference to the MBean server in which it is
* registered.
* <p>
* This method is called by the MBean server. Application classes should
* not call this method directly. Subclasses are free to override this
* method with their own specific behavior - but the overriding method
* shoud still call {@code super.postRegister(registrationDone)}.
* @see MBeanRegistration#postRegister MBeanRegistration
*/
public void postRegister(Boolean registrationDone) {
// nothing to do
}
/**
* This method is part of the {@link MBeanRegistration} interface.
* The {@link JMXNamespace} class uses the {@link MBeanRegistration}
* interface in order to get a reference to the MBean server in which it is
* registered.
* <p>
* This method is called by the MBean server. Application classes should
* not call this method directly. Subclasses are free to override this
* method with their own specific behavior - but the overriding method
* shoud still call {@code super.preDeregister()}.
* @see MBeanRegistration#preDeregister MBeanRegistration
*/
public void preDeregister() throws Exception {
// nothing to do
}
/**
* This method is part of the {@link MBeanRegistration} interface.
* It allows the {@code JMXNamespace} MBean to perform any operations
* needed after having been unregistered in the MBean server.
* <p>
* This method is called by the MBean server. Application classes should
* not call this method directly. If a subclass overrides this
* method, the overriding method shoud call {@code super.postDeregister()}.
* @see MBeanRegistration#postDeregister MBeanRegistration
*/
public void postDeregister() {
// need to synchronize to protect against multiple registration.
synchronized(this) {
mbeanServer = null;
objectName = null;
}
}
/**
* Returns the MBeanServer in which this MBean is registered,
* or null. Chiefly of interest for subclasses.
* @return the MBeanServer supplied to {@link #preRegister}.
**/
public final MBeanServer getMBeanServer() {
return mbeanServer;
}
/**
* Returns the MBeanServer that contains or emulates the source
* namespace. When a JMXNamespace MBean is registered in an
* MBean server created through the default {@link
* javax.management.MBeanServerBuilder}, the MBeanServer will
* check {@link JMXNamespacePermission} before invoking
* any method on the source MBeanServer of the JMXNamespace.
* See <a href="#PermissionChecks">JMX Namespace Permission Checks</a>
* above.
* @return an MBeanServer view of the source namespace
**/
public MBeanServer getSourceServer() {
return sourceServer;
}
/**
* Returns the ObjectName with which this MBean was registered,
* or null. Chiefly of interest for subclasses.
* @return the ObjectName supplied to {@link #preRegister}.
**/
public final ObjectName getObjectName() {
return objectName;
}
/**
* HandlerName used in traces.
**/
String getHandlerName() {
final ObjectName name = getObjectName();
if (name != null) return name.toString();
return this.toString();
}
/**
* In this class, this method returns {@link #getSourceServer
* getSourceServer()}.{@link javax.management.MBeanServer#getMBeanCount
* getMBeanCount()}.
* <br>This default behaviour may be redefined in subclasses.
* @throws java.io.IOException can be thrown by subclasses.
*/
public Integer getMBeanCount() throws IOException {
return getSourceServer().getMBeanCount();
}
/**
* In this class, this method returns {@link #getSourceServer
* getSourceServer()}.{@link javax.management.MBeanServer#getDomains
* getDomains()}.
* <br>This default behaviour may be redefined in subclasses.
* @throws java.io.IOException can be thrown by subclasses.
*/
public String[] getDomains() throws IOException {
return getSourceServer().getDomains();
}
/**
* In this class, this method returns {@link #getSourceServer
* getSourceServer()}.{@link javax.management.MBeanServer#getDefaultDomain
* getDefaultDomain()}.
* <br>This default behaviour may be redefined in subclasses.
* @throws java.io.IOException can be thrown by subclasses.
*/
public String getDefaultDomain() throws IOException {
return getSourceServer().getDefaultDomain();
}
public final String getUUID() {
return uuid;
}
}