jdk/src/share/classes/javax/management/namespace/JMXNamespace.java
changeset 1156 bbc2d15aaf7a
child 1222 78e3d021d528
equal deleted inserted replaced
1155:a9a142fcf1b5 1156:bbc2d15aaf7a
       
     1 /*
       
     2  * Copyright 2008 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.namespace;
       
    27 
       
    28 
       
    29 import java.io.IOException;
       
    30 
       
    31 import java.util.UUID;
       
    32 import javax.management.MBeanRegistration;
       
    33 import javax.management.MBeanServer;
       
    34 import javax.management.ObjectName;
       
    35 
       
    36 /**
       
    37  * MBean Servers can be federated into a single hierarchical name space:
       
    38  * A JMXNamespace is an MBean that handles a sub name space in that
       
    39  * hierarchical name space.
       
    40  * <p>
       
    41  * A name space is created simply by registering a {@code JMXNamespace}
       
    42  * MBean in the MBean Server. The name of the created name space is defined
       
    43  * by the {@linkplain JMXNamespaces#getNamespaceObjectName name of the JMXNamespace}
       
    44  * that handles it. A name space is equivalent to
       
    45  * an MBean Server within an MBean Server. When creating a {@code JMXNamespace},
       
    46  * the MBean Server within is passed to the constructor.
       
    47  * </p>
       
    48  * <p>
       
    49  * The {@code JMXNamespace} class is the base class for implementing
       
    50  * all name space handlers. All name space handlers must be instances of
       
    51  * {@code JMXNamespace} or a subclass of it.
       
    52  * </p>
       
    53  * <p>
       
    54  * A concrete example of a {@code JMXNamespace} MBean subclass
       
    55  * is the {@link JMXRemoteNamespace JMXRemoteNamespace} MBean which
       
    56  * is able to mirror all MBeans contained in a remote MBean server known by its
       
    57  * {@link javax.management.remote.JMXServiceURL}.
       
    58  * </p>
       
    59  * <p>
       
    60  * You can create a local namespace by supplying a newly created MBean Server
       
    61  * to an instance of {@code JMXNamespace}. For instance:
       
    62  * <pre>
       
    63  * final String namespace = "foo";
       
    64  * final ObjectName namespaceName = {@link JMXNamespaces#getNamespaceObjectName
       
    65  *       JMXNamespaces.getNamespaceObjectName(namespace)};
       
    66  * server.registerMBean(new JMXNamespace(MBeanServerFactory.newMBeanServer()),
       
    67  *                      namespaceName);
       
    68  * </pre>
       
    69  * </p>
       
    70  * <p>
       
    71  * <u>Note:</u> A JMXNamespace MBean cannot be registered
       
    72  * simultaneously in two different
       
    73  * MBean servers, or indeed in the same MBean Server with two
       
    74  * different names. It is however possible to give the same MBeanServer
       
    75  * instance to two different JMXNamespace MBeans, and thus create a graph
       
    76  * rather than a tree.
       
    77  * </p>
       
    78  *
       
    79  * <p>To view the content of a namespace, you will usually use an
       
    80  *    instance of {@link JMXNamespaceView}. For instance, given the
       
    81  *    namespace {@code "foo"} created above, you would do:
       
    82  * </p>
       
    83  * <pre>
       
    84  * final JMXNamespaceView view = new JMXNamespaceView(server);
       
    85  * System.out.println("List of namespaces: "+Arrays.toString({@link JMXNamespaceView#list() view.list()}));
       
    86  *
       
    87  * final JMXNamespaceView foo  = {@link JMXNamespaceView#down view.down("foo")};
       
    88  * System.out.println({@link JMXNamespaceView#where() foo.where()}+" contains: " +
       
    89  *        {@link JMXNamespaceView#getMBeanServerConnection foo.getMBeanServerConnection()}.queryNames(null,null));
       
    90  * </pre>
       
    91  *
       
    92  * <h2 id="PermissionChecks">JMX Namespace Permission Checks</h2>
       
    93  *
       
    94  * <p>A special {@link JMXNamespacePermission} is defined to check access
       
    95  * to MBean within namespaces.</p>
       
    96  * <p>When a JMXNamespace MBean is registered in an
       
    97  * MBean server created through the default {@link
       
    98  * javax.management.MBeanServerBuilder}, and if a {@link
       
    99  * SecurityManager SecurityManager} is
       
   100  * {@linkplain System#getSecurityManager() present}, the MBeanServer will
       
   101  * check a {@link JMXNamespacePermission} before invoking
       
   102  * any method on the {@linkplain #getSourceServer source MBeanServer} of the
       
   103  * JMXNamespace.
       
   104  * {@linkplain JMXNamespacePermission JMX Namespace Permissions} are similar to
       
   105  * {@linkplain javax.management.MBeanPermission MBean Permissions}, except
       
   106  * that you usually cannot specify an MBean class name. You can however
       
   107  * specify object name patterns - which will allow you for example to only grant
       
   108  * permissions for MBeans having a specific {@code type=<MBeanType>} key
       
   109  * in their object name.
       
   110  * <p>
       
   111  * Another difference is that {@link JMXNamespacePermission
       
   112  * JMXNamespacePermission} also specifies from which namespace and which
       
   113  * MBean server the permission is granted.
       
   114  * </p>
       
   115  * <p>In the rest of this document, the following terms are used:</p>
       
   116  * <ul>
       
   117  *    <li id="MBeanServerName"><p>{@code server name} is the
       
   118  *    <a href="../MBeanServerFactory.html#MBeanServerName">name of the
       
   119  *    MBeanServer</a> in which the permission is granted.
       
   120  *    The name of an {@code MBeanServer} can be obtained by calling {@link
       
   121  *    javax.management.MBeanServerFactory#getMBeanServerName
       
   122  *    MBeanServerFactory.getMBeanServerName(mbeanServer)}
       
   123  *    </p>
       
   124  *    <li id="NamespaceName"><p>{@code namespace} is the name of the namespace
       
   125  *    in the <a href="#MBeanServerName">named MBean server</a> for which the
       
   126  *    permission is granted. It doesn't contain any
       
   127  *    {@link JMXNamespaces#NAMESPACE_SEPARATOR namespace separator}.
       
   128  *    </p>
       
   129  *    <li id="MBeanName"><p>{@code mbean} is the name
       
   130  *    of the MBean in that {@code namespace}. This is the name of the MBean
       
   131  *    in the namespace's {@link JMXNamespace#getSourceServer() source mbean server}.
       
   132  *    It might contain no, one, or several {@link
       
   133  *    JMXNamespaces#NAMESPACE_SEPARATOR namespace separators}.
       
   134  *    </p>
       
   135  * </ul>
       
   136  *
       
   137  * <p>For instance let's assume that some piece of code calls:</p>
       
   138  * <pre>
       
   139  *     final MBeanServer mbeanServer = ...;
       
   140  *     final ObjectName  name   = new ObjectName("a//b//c//D:k=v");
       
   141  *     mbeanServer.getAttribute(name,"Foo");
       
   142  * </pre>
       
   143  * <p>
       
   144  *   Assuming that there is a security manager, or that the
       
   145  *   implementation chooses to make checks anyway, the checks that will
       
   146  *   be made in that case are:
       
   147  * </p>
       
   148  * <ol>
       
   149  * <li id="check1">
       
   150  * <code>JMXNamespacePermission(mbeanServerName, "Foo", "<b>a//</b>b//c//D:k=v",
       
   151  * "getAttribute")</code>
       
   152  * (where {@code mbeanServerName=MBeanServerFactory.getMBeanServerName(mbeanServer)},
       
   153  * <code>namespace="<b>a</b>"</code>, and {@code mbean="b//c//D:k=v"})
       
   154  * </li>
       
   155  * <li id="check2">and in addition if namespace {@code "a"} is local,
       
   156  * <code>JMXNamespacePermission(aSourceServerName,"Foo","<b>b//</b>c//D:k=v",
       
   157  *       "getAttribute")}</code>
       
   158  * (where
       
   159  * {@code aSourceServerName=MBeanServerFactory.getMBeanServerName(sourceServer(a))},
       
   160  * <code>namespace="<b>b</b>"</code>, and {@code mbean="c//D:k=v"}),
       
   161  * </li>
       
   162  * <li id="check3">and in addition if namespace {@code "b"} is also local,
       
   163  * <code>JMXNamespacePermission(bSourceServerName,"Foo","<b>c//</b>D:k=v",
       
   164  *       "getAttribute")}</code>
       
   165  * (where
       
   166  * {@code bSourceServerName=MBeanServerFactory.getMBeanServerName(sourceServer(b))},
       
   167  * <code>namespace="<b>c</b>"</code>, and {@code mbean="D:k=v"}),
       
   168  * </li>
       
   169  * <li id="check4">and in addition if the source mbean server of namespace
       
   170  * {@code "c"} is a also a local MBeanServer in this JVM,
       
   171  * {@code MBeanPermission(cSourceServerName,<className(D:k=v)>,"Foo","D:k=v","getAttrinute")},
       
   172  * (where
       
   173  * {@code cSourceServerName=MBeanServerFactory.getMBeanServerName(sourceServer(c))}).
       
   174  * </li>
       
   175  * </ol>
       
   176  * <p>For any of these MBean servers, if no name was supplied when
       
   177  * creating that MBeanServer the {@link JMXNamespacePermission} is
       
   178  * created with an {@code mbeanServerName} equal to
       
   179  * {@value javax.management.MBeanServerFactory#DEFAULT_MBEANSERVER_NAME}.
       
   180  * </p>
       
   181  * <p>If the namespace {@code a} is in fact a remote {@code MBeanServer},
       
   182  *    for instance because namespace {@code a} is implemented by a {@link
       
   183  *    JMXRemoteNamespace} pointing to a distant MBeanServer located in
       
   184  *    another JMX agent, then checks <a href="#check2">2</a>,
       
   185  *    <a href="#check3">3</a>, and <a href="#check4">4</a> will not
       
   186  *    be performed in the local JVM. They might or might not be performed in
       
   187  *    the remote agent, depending on how access control and permission
       
   188  *    checking are configured in the remote agent, and how authentication
       
   189  *    is configured in the connector used by the {@link
       
   190  *    JMXRemoteNamespace}.
       
   191  * </p>
       
   192  * <p>In all cases, {@linkplain JMXNamespacePermission JMX Namespace Permissions}
       
   193  * are checked as follows:</p>
       
   194  * <p>First, if there is no security manager ({@link
       
   195  * System#getSecurityManager()} is null), then an implementation of
       
   196  * of MBeanServer that supports JMX namespaces is free not to make any
       
   197  * checks.</p>
       
   198  *
       
   199  * <p>Assuming that there is a security manager, or that the
       
   200  * implementation chooses to make checks anyway, the checks are made
       
   201  * as detailed below.</p>
       
   202  *
       
   203  * <p>If a security check fails, the method throws {@link
       
   204  * SecurityException}.</p>
       
   205  *
       
   206  * <ul>
       
   207  *
       
   208  * <li><p>For the {@link MBeanServer#invoke invoke} method, the caller's
       
   209  * permissions must imply {@link
       
   210  * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
       
   211  * JMXNamespacePermission(&lt;mbean server name&gt;, &lt;operation name&gt;, &lt;namespace&gt;//&lt;mbean&gt;, "invoke")},
       
   212  * where <a href="#MBeanServerName">mbean server name</a> is the name of the
       
   213  * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
       
   214  * <a href="#NamespaceName">namespace</a> is registered, and
       
   215  * <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
       
   216  * is performed, in that namespace.
       
   217  * </p>
       
   218  *
       
   219  * <li><p>For the {@link MBeanServer#getAttribute getAttribute} method, the
       
   220  * caller's permissions must imply {@link
       
   221  * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
       
   222  * JMXNamespacePermission(&lt;mbean server name&gt;, &lt;attribute&gt;, &lt;namespace&gt;//&lt;mbean&gt;, "getAttribute")}.
       
   223  * </p>
       
   224  *
       
   225  * <li><p>For the {@link MBeanServer#getAttributes getAttributes} method, the
       
   226  * caller's permissions must imply {@link
       
   227  * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
       
   228  * JMXNamespacePermission(&lt;mbean server name&gt;, &lt;null&gt;, &lt;namespace&gt;//&lt;mbean&gt;, "getAttribute")},
       
   229  * where <a href="#MBeanServerName">mbean server name</a> is the name of the
       
   230  * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
       
   231  * <a href="#NamespaceName">namespace</a> is registered, and
       
   232  * <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
       
   233  * is performed, in that namespace.
       
   234  * Additionally, for each attribute <em>att</em> in the {@link
       
   235  * javax.management.AttributeList}, if the caller's permissions do not
       
   236  * imply {@link
       
   237  * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
       
   238  * JMXNamespacePermission(&lt;mbean server name&gt;, <em>att</em>,
       
   239  * &lt;namespace&gt;//&lt;mbean&gt;, "getAttribute")}, the
       
   240  * MBean server will behave as if that attribute had not been in the
       
   241  * supplied list.</p>
       
   242  *
       
   243  * <li><p>For the {@link MBeanServer#setAttribute setAttribute} method, the
       
   244  * caller's permissions must imply {@link
       
   245  * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
       
   246  * JMXNamespacePermission(&lt;mbean server name&gt;, &lt;attrName&gt;, &lt;namespace&gt;//&lt;mbean&gt;, "setAttribute")},
       
   247  * where <a href="#MBeanServerName">mbean server name</a> is the name of the
       
   248  * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
       
   249  * <a href="#NamespaceName">namespace</a> is registered, and
       
   250  * <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
       
   251  * is performed, in that namespace, and
       
   252  * <code>attrName</code> is {@link javax.management.Attribute#getName()
       
   253  * attribute.getName()}.</p>
       
   254  *
       
   255  * <li><p>For the {@link MBeanServer#setAttributes setAttributes} method, the
       
   256  * caller's permissions must imply {@link
       
   257  * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
       
   258  * JMXNamespacePermission(&lt;mbean server name&gt;, null, &lt;namespace&gt;//&lt;mbean&gt;, "setAttribute")},
       
   259  * where <a href="#MBeanServerName">mbean server name</a> is the name of the
       
   260  * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
       
   261  * <a href="#NamespaceName">namespace</a> is registered, and
       
   262  * <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
       
   263  * is performed, in that namespace.
       
   264  * Additionally, for each attribute <em>att</em> in the {@link
       
   265  * javax.management.AttributeList}, if the caller's permissions do not
       
   266  * imply {@link
       
   267  * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
       
   268  * JMXNamespacePermission(&lt;mbean server name&gt;, <em>att</em>, &lt;namespace&gt;//&lt;mbean&gt;, "setAttribute")},
       
   269  * the MBean server will behave as if that attribute had not been in the
       
   270  * supplied list.</p>
       
   271  *
       
   272  * <li><p>For the <code>addNotificationListener</code> methods,
       
   273  * the caller's permissions must imply {@link
       
   274  * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
       
   275  * JMXNamespacePermission(&lt;mbean server name&gt;, null, &lt;namespace&gt;//&lt;mbean&gt;,
       
   276  * "addNotificationListener")},
       
   277  * where <a href="#MBeanServerName">mbean server name</a> is the name of the
       
   278  * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
       
   279  * <a href="#NamespaceName">namespace</a> is registered, and
       
   280  * <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
       
   281  * is performed, in that namespace.
       
   282  * </p>
       
   283  *
       
   284  * <li><p>For the <code>removeNotificationListener</code> methods,
       
   285  * the caller's permissions must imply {@link
       
   286  * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
       
   287  * JMXNamespacePermission(&lt;mbean server name&gt;, null, &lt;namespace&gt;//&lt;mbean&gt;,
       
   288  * "removeNotificationListener")},
       
   289  * where <a href="#MBeanServerName">mbean server name</a> is the name of the
       
   290  * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
       
   291  * <a href="#NamespaceName">namespace</a> is registered, and
       
   292  * <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
       
   293  * is performed, in that namespace.
       
   294  * </p>
       
   295  *
       
   296  * <li><p>For the {@link MBeanServer#getMBeanInfo getMBeanInfo} method, the
       
   297  * caller's permissions must imply {@link
       
   298  * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
       
   299  * JMXNamespacePermission(&lt;mbean server name&gt;, null, &lt;namespace&gt;//&lt;mbean&gt;,
       
   300  * "getMBeanInfo")},
       
   301  * where <a href="#MBeanServerName">mbean server name</a> is the name of the
       
   302  * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
       
   303  * <a href="#NamespaceName">namespace</a> is registered, and
       
   304  * <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
       
   305  * is performed, in that namespace.
       
   306  * </p>
       
   307  *
       
   308  * <li><p>For the {@link MBeanServer#getObjectInstance getObjectInstance} method,
       
   309  * the caller's permissions must imply {@link
       
   310  * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
       
   311  * JMXNamespacePermission(&lt;mbean server name&gt;, null, &lt;namespace&gt;//&lt;mbean&gt;,
       
   312  * "getObjectInstance")},
       
   313  * where <a href="#MBeanServerName">mbean server name/a> is the name of the
       
   314  * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
       
   315  * <a href="#NamespaceName">namespace</a> is registered, and
       
   316  * <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
       
   317  * is performed, in that namespace.
       
   318  * </p>
       
   319  *
       
   320  * <li><p>For the {@link MBeanServer#isInstanceOf isInstanceOf} method, the
       
   321  * caller's permissions must imply {@link
       
   322  * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
       
   323  * JMXNamespacePermission(&lt;mbean server name&gt;, null, &lt;namespace&gt;//&lt;mbean&gt;,
       
   324  * "isInstanceOf")},
       
   325  * where <a href="#MBeanServerName">mbean server name</a> is the name of the
       
   326  * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
       
   327  * <a href="#NamespaceName">namespace</a> is registered, and
       
   328  * <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
       
   329  * is performed, in that namespace.
       
   330  * </p>
       
   331  *
       
   332  * <li><p>For the {@link MBeanServer#queryMBeans queryMBeans} method, the
       
   333  * caller's permissions must imply {@link
       
   334  * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
       
   335  * JMXNamespacePermission(&lt;mbean server name&gt;, null, null,
       
   336  * "queryMBeans")}.
       
   337  * Additionally, for each MBean {@code mbean} that matches {@code pattern},
       
   338  * if the caller's permissions do not imply {@link
       
   339  * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
       
   340  * JMXNamespacePermission(&lt;mbean server name&gt;, null, &lt;namespace&gt;//&lt;mbean&gt;,
       
   341  * "queryMBeans")}, the
       
   342  * MBean server will behave as if that MBean did not exist.</p>
       
   343  *
       
   344  * <p>Certain query elements perform operations on the MBean server.
       
   345  * However these operations are usually performed by the MBeanServer at the
       
   346  * bottom of the namespace path, and therefore, do not involve any
       
   347  * {@link JMXNamespacePermission} permission check. They might involve
       
   348  * {@link javax.management.MBeanPermission} checks depending on how security
       
   349  * in the JVM in which the bottom MBeanServer resides is implemented.
       
   350  * See {@link javax.management.MBeanServer} for more details.
       
   351  * </p>
       
   352  *
       
   353  * <li><p>For the {@link MBeanServer#queryNames queryNames} method, the checks
       
   354  * are the same as for <code>queryMBeans</code> except that
       
   355  * <code>"queryNames"</code> is used instead of
       
   356  * <code>"queryMBeans"</code> in the <code>JMXNamespacePermission</code>
       
   357  * objects.  Note that a <code>"queryMBeans"</code> permission implies
       
   358  * the corresponding <code>"queryNames"</code> permission.</p>
       
   359  *
       
   360  * <li><p>For the {@link MBeanServer#getClassLoader getClassLoader} method, the
       
   361  * caller's permissions must imply {@link
       
   362  * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
       
   363  * JMXNamespacePermission(&lt;mbean server name&gt;, null, &lt;namespace&gt;//&lt;loaderName&gt;,
       
   364  * "getClassLoader")},
       
   365  * where <a href="#MBeanServerName">mbean server name/a> is the name of the
       
   366  * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
       
   367  * <a href="#NamespaceName">namespace</a> is registered, and
       
   368  * <a href="#MBeanName">loaderName</a> is the name of the ClassLoader MBean
       
   369  * which is accessed, in that namespace.
       
   370  * </p>
       
   371  *
       
   372  * <li><p>For the {@link MBeanServer#getClassLoaderFor getClassLoaderFor} method,
       
   373  * the caller's permissions must imply {@link
       
   374  * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
       
   375  * JMXNamespacePermission(&lt;mbean server name&gt;, null, &lt;namespace&gt;//&lt;mbean&gt;,
       
   376  * "getClassLoaderFor")},
       
   377  * where <a href="#MBeanServerName">mbean server name</a> is the name of the
       
   378  * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
       
   379  * <a href="#NamespaceName">namespace</a> is registered, and
       
   380  * <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
       
   381  * is performed, in that namespace.
       
   382  * </p>
       
   383  *
       
   384  * <li><p>For the {@link MBeanServer#registerMBean registerMBean} method, the
       
   385  * caller's permissions must imply {@link
       
   386  * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
       
   387  * JMXNamespacePermission(&lt;mbean server name&gt;, &lt;class name&gt;, &lt;namespace&gt;//&lt;mbean&gt;,
       
   388  * "registerMBean")}.  Here
       
   389  * <code>class name</code> is the string returned by {@code
       
   390  * obj.getClass().getName()} where {@code obj} is the mbean reference,
       
   391  * <a href="#MBeanServerName"mbean server name/a> is the name of the
       
   392  * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
       
   393  * <a href="#NamespaceName">namespace</a> is registered, and
       
   394  * <a href="#MBeanName">mbean</a> is the name of the MBean which is being
       
   395  * registered, relative to that namespace.
       
   396  *
       
   397  * <li><p>For the <code>createMBean</code> methods, the caller's
       
   398  * permissions must imply {@link
       
   399  * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
       
   400  * JMXNamespacePermission(&lt;mbean server name&gt;, &lt;class name&gt;, &lt;namespace&gt;//&lt;mbean&gt;,
       
   401  * "instantiate")} and
       
   402  * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
       
   403  * JMXNamespacePermission(&lt;mbean server name&gt;, &lt;class name&gt;, &lt;namespace&gt;//&lt;mbean&gt;,
       
   404  * "registerMBean")}, where
       
   405  * <code>class name</code> is the string passed as first argument to the {@code
       
   406  * createMBean} method,
       
   407  * <a href="#MBeanServerName">mbean server name</a> is the name of the
       
   408  * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
       
   409  * <a href="#NamespaceName">namespace</a> is registered, and
       
   410  * <a href="#MBeanName">mbean</a> is the name of the MBean which is being
       
   411  * created, relative to that namespace.
       
   412  *
       
   413  * <li><p>For the {@link MBeanServer#unregisterMBean unregisterMBean} method,
       
   414  * the caller's permissions must imply {@link
       
   415  * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
       
   416  * JMXNamespacePermission(&lt;mbean server name&gt;, null, &lt;namespace&gt;//&lt;mbean&gt;,
       
   417  * "unregisterMBean")},
       
   418  * where <a href="#MBeanServerName">mbean server name</a> is the name of the
       
   419  * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
       
   420  * <a href="#NamespaceName">namespace</a> is registered, and
       
   421  * <a href="#MBeanName">mbean</a> is the name of the MBean on which is
       
   422  * being unregistered, relative to that namespace.
       
   423  * </p>
       
   424  * </ul>
       
   425  * </p>
       
   426  * <p>It must be noted that if all namespaces are local, and all
       
   427  *    local namespaces are implemented by regular MBean servers, that is, there
       
   428  *    are no {@linkplain MBeanServerSupport Virtual Namespaces}, then
       
   429  *    simple {@linkplain javax.management.MBeanPermission MBean Permission}
       
   430  *    checks might be enough to secure an application.
       
   431  *    In that case, it is possible to specify the following {@link
       
   432  *    JMXNamespacePermission} permission in the policy file, which implies all
       
   433  *    other JMX namespace permissions:
       
   434  * </p>
       
   435  * <pre>
       
   436  *     permission javax.management.namespace.JMXNamespacePermission "*::*[]", "*";
       
   437  * </pre>
       
   438  *
       
   439  * @since 1.7
       
   440  */
       
   441 public class JMXNamespace
       
   442         implements JMXNamespaceMBean, MBeanRegistration {
       
   443 
       
   444     /**
       
   445      * The standard value of the {@code type}
       
   446      * property key that must be used to construct valid {@link
       
   447      * JMXNamespaceMBean} ObjectNames.<br>
       
   448      * This is {@value #TYPE}.
       
   449      **/
       
   450     public static final String TYPE = "JMXNamespace";
       
   451 
       
   452     /**
       
   453      * The {@link ObjectName#getKeyPropertyListString keyPropertyListString}
       
   454      * that must be used to construct valid {@link JMXNamespaceMBean}
       
   455      * ObjectNames.<br>
       
   456      * This is
       
   457      * <code>{@value #TYPE_ASSIGNMENT}</code>.
       
   458      **/
       
   459     public static final String TYPE_ASSIGNMENT = "type="+TYPE;
       
   460 
       
   461     private volatile MBeanServer mbeanServer; // the mbean server in which
       
   462                                               // this MBean is registered.
       
   463     private volatile ObjectName objectName;   // the ObjectName of this MBean.
       
   464     private final MBeanServer sourceServer;   // the MBeanServer within = the
       
   465                                               // name space (or the MBean server
       
   466                                               // that contains it).
       
   467     private final String uuid;
       
   468 
       
   469     /**
       
   470      * Creates a new JMXNamespace implemented by means of an MBean Server.
       
   471      * A namespace is equivalent to an MBeanServer within an MBean Server.
       
   472      * The {@code sourceServer} provided to this constructor is the MBean Server
       
   473      * within.
       
   474      * @param sourceServer the MBean server that implemented by this namespace.
       
   475      * @see #getSourceServer
       
   476     */
       
   477     public JMXNamespace(MBeanServer sourceServer) {
       
   478         this.sourceServer = sourceServer;
       
   479         this.uuid = UUID.randomUUID().toString();
       
   480     }
       
   481 
       
   482     /**
       
   483      * This method is part of the {@link MBeanRegistration} interface.
       
   484      * The {@link JMXNamespace} class uses the {@link MBeanRegistration}
       
   485      * interface in order to get a handle to the MBean server in which it is
       
   486      * registered. It also check the validity of its own ObjectName.
       
   487      * <p>
       
   488      * This method is called by the MBean server.
       
   489      * Application classes should never call this method directly.
       
   490      * <p>
       
   491      * If this method is overridden, the overriding method should call
       
   492      * {@code super.preRegister(server,name)}.
       
   493      * @see MBeanRegistration#preRegister MBeanRegistration
       
   494      * @see JMXNamespaces#getNamespaceObjectName getNamespaceObjectName
       
   495      * @param name The object name of the MBean. <var>name</var> must be a
       
   496      *  syntactically valid JMXNamespace name, as returned by
       
   497      *  {@link JMXNamespaces#getNamespaceObjectName(java.lang.String)
       
   498      *   getNamespaceObjectName(namespace)}.
       
   499      * @return The name under which the MBean is to be registered.
       
   500      * @throws IllegalArgumentException if the name supplied is not valid.
       
   501      * @throws Exception can be thrown by subclasses.
       
   502      */
       
   503     public ObjectName preRegister(MBeanServer server, ObjectName name)
       
   504         throws Exception {
       
   505         if (objectName != null && ! objectName.equals(name))
       
   506             throw new IllegalStateException(
       
   507                     "Already registered under another name: " + objectName);
       
   508         objectName = validateHandlerName(name);
       
   509         mbeanServer = server;
       
   510         return name;
       
   511     }
       
   512 
       
   513     /**
       
   514      * Validate the ObjectName supplied to preRegister.
       
   515      * This method is introduced to allow standard subclasses to use
       
   516      * an alternate naming scheme. For instance - if we want to
       
   517      * reuse JMXNamespace in order to implement sessions...
       
   518      * It is however only available for subclasses in this package.
       
   519      **/
       
   520     ObjectName validateHandlerName(ObjectName supliedName) {
       
   521         if (supliedName == null)
       
   522             throw new IllegalArgumentException("Must supply a valid name");
       
   523         final String dirName = JMXNamespaces.
       
   524                 normalizeNamespaceName(supliedName.getDomain());
       
   525         final ObjectName handlerName =
       
   526                 JMXNamespaces.getNamespaceObjectName(dirName);
       
   527         if (!supliedName.equals(handlerName))
       
   528             throw new IllegalArgumentException("invalid name space name: "+
       
   529                         supliedName);
       
   530         return supliedName;
       
   531     }
       
   532 
       
   533     /**
       
   534      * This method is part of the {@link MBeanRegistration} interface.
       
   535      * The {@link JMXNamespace} class uses the {@link MBeanRegistration}
       
   536      * interface in order to get a handle to the MBean server in which it is
       
   537      * registered.
       
   538      * <p>
       
   539      * This method is called by the MBean server. Application classes should
       
   540      * not call this method directly. Subclasses are free to override this
       
   541      * method with their own specific behavior - but the overriding method
       
   542      * shoud still call {@code super.postRegister(registrationDone)}.
       
   543      * @see MBeanRegistration#postRegister MBeanRegistration
       
   544      */
       
   545     public void postRegister(Boolean registrationDone) {
       
   546         // nothing to do
       
   547     }
       
   548 
       
   549     /**
       
   550      * This method is part of the {@link MBeanRegistration} interface.
       
   551      * The {@link JMXNamespace} class uses the {@link MBeanRegistration}
       
   552      * interface in order to get a handle to the MBean server in which it is
       
   553      * registered.
       
   554      * <p>
       
   555      * This method is called by the MBean server. Application classes should
       
   556      * not call this method directly. Subclasses are free to override this
       
   557      * method with their own specific behavior - but the overriding method
       
   558      * shoud still call {@code super.preDeregister()}.
       
   559      * @see MBeanRegistration#preDeregister MBeanRegistration
       
   560      */
       
   561     public void preDeregister() throws Exception {
       
   562         // nothing to do
       
   563     }
       
   564 
       
   565     /**
       
   566      * This method is part of the {@link MBeanRegistration} interface.
       
   567      * It allows the {@code JMXNamespace} MBean to perform any operations
       
   568      * needed after having been unregistered in the MBean server.
       
   569      * <p>
       
   570      * This method is called by the MBean server. Application classes should
       
   571      * not call this method directly. If a subclass overrides this
       
   572      * method, the overriding method shoud  call {@code super.postDeregister()}.
       
   573      * @see MBeanRegistration#postDeregister MBeanRegistration
       
   574      */
       
   575     public void postDeregister() {
       
   576         mbeanServer = null;
       
   577         objectName  = null;
       
   578     }
       
   579 
       
   580 
       
   581     /**
       
   582      * Returns the MBeanServer in which this MBean is registered,
       
   583      * or null. Chiefly of interest for subclasses.
       
   584      * @return the MBeanServer supplied to {@link #preRegister}.
       
   585      **/
       
   586     public final MBeanServer getMBeanServer() {
       
   587         return mbeanServer;
       
   588     }
       
   589 
       
   590     /**
       
   591      * Returns the MBeanServer that contains or emulates the source
       
   592      * namespace. When a JMXNamespace MBean is registered in an
       
   593      * MBean server created through the default {@link
       
   594      * javax.management.MBeanServerBuilder}, the MBeanServer will
       
   595      * check {@link JMXNamespacePermission} before invoking
       
   596      * any method on the source MBeanServer of the JMXNamespace.
       
   597      * See <a href="#PermissionChecks">JMX Namespace Permission Checks</a>
       
   598      * above.
       
   599      * @return an MBeanServer view of the source namespace
       
   600      **/
       
   601     public MBeanServer getSourceServer() {
       
   602         return sourceServer;
       
   603     }
       
   604 
       
   605     /**
       
   606      * Returns the ObjectName with which this MBean was registered,
       
   607      * or null. Chiefly of interest for subclasses.
       
   608      * @return the ObjectName supplied to {@link #preRegister}.
       
   609      **/
       
   610     public final ObjectName getObjectName() {
       
   611         return objectName;
       
   612     }
       
   613 
       
   614     /**
       
   615      * HandlerName used in traces.
       
   616      **/
       
   617     String getHandlerName() {
       
   618         final ObjectName name = getObjectName();
       
   619         if (name != null) return name.toString();
       
   620         return this.toString();
       
   621     }
       
   622 
       
   623    /**
       
   624     * In this class, this method returns {@link #getSourceServer
       
   625     * getSourceServer()}.{@link javax.management.MBeanServer#getMBeanCount
       
   626     * getMBeanCount()}.
       
   627     * <br>This default behaviour may be redefined in subclasses.
       
   628     * @throws java.io.IOException can be thrown by subclasses.
       
   629     */
       
   630     public Integer getMBeanCount() throws IOException {
       
   631         return getSourceServer().getMBeanCount();
       
   632     }
       
   633 
       
   634    /**
       
   635     * In this class, this method returns {@link #getSourceServer
       
   636     * getSourceServer()}.{@link javax.management.MBeanServer#getDomains
       
   637     * getDomains()}.
       
   638     * <br>This default behaviour may be redefined in subclasses.
       
   639     * @throws java.io.IOException can be thrown by subclasses.
       
   640     */
       
   641    public String[] getDomains() throws IOException {
       
   642        return getSourceServer().getDomains();
       
   643     }
       
   644 
       
   645    /**
       
   646     * In this class, this method returns {@link #getSourceServer
       
   647     * getSourceServer()}.{@link javax.management.MBeanServer#getDefaultDomain
       
   648     * getDefaultDomain()}.
       
   649     * <br>This default behaviour may be redefined in subclasses.
       
   650     * @throws java.io.IOException can be thrown by subclasses.
       
   651     */
       
   652     public String getDefaultDomain() throws IOException {
       
   653         return getSourceServer().getDefaultDomain();
       
   654     }
       
   655 
       
   656     public final String getUUID() {
       
   657         return uuid;
       
   658     }
       
   659 
       
   660 }