jdk/src/share/classes/com/sun/jmx/interceptor/NamespaceDispatchInterceptor.java
changeset 1156 bbc2d15aaf7a
child 1222 78e3d021d528
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/jmx/interceptor/NamespaceDispatchInterceptor.java	Thu Sep 04 14:46:36 2008 +0200
@@ -0,0 +1,236 @@
+/*
+ * 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 com.sun.jmx.interceptor;
+
+import com.sun.jmx.defaults.JmxProperties;
+import com.sun.jmx.mbeanserver.MBeanInstantiator;
+import com.sun.jmx.mbeanserver.Repository;
+import com.sun.jmx.mbeanserver.Util;
+import com.sun.jmx.namespace.NamespaceInterceptor;
+
+import java.util.Queue;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerDelegate;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+import javax.management.namespace.JMXDomain;
+import javax.management.namespace.JMXNamespace;
+import static javax.management.namespace.JMXNamespaces.NAMESPACE_SEPARATOR;
+
+/**
+ * A dispatcher that dispatches to NamespaceInterceptors.
+ * <p><b>
+ * This API is a Sun internal API and is subject to changes without notice.
+ * </b></p>
+ * @since 1.7
+ */
+public class NamespaceDispatchInterceptor
+        extends DispatchInterceptor<NamespaceInterceptor, JMXNamespace> {
+
+    /**
+     * A logger for this class.
+     **/
+    private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER;
+
+    private static final int NAMESPACE_SEPARATOR_LENGTH =
+            NAMESPACE_SEPARATOR.length();
+
+    private final DomainDispatchInterceptor localNamespace;
+    private final String           serverName;
+
+    /**
+     * Creates a NamespaceDispatchInterceptor with the specified
+     * repository instance.
+     * <p>Do not forget to call <code>initialize(outer,delegate)</code>
+     * before using this object.
+     *
+     * @param outer A pointer to the MBeanServer object that must be
+     *        passed to the MBeans when invoking their
+     *        {@link javax.management.MBeanRegistration} interface.
+     * @param delegate A pointer to the MBeanServerDelegate associated
+     *        with the new MBeanServer. The new MBeanServer must register
+     *        this MBean in its MBean repository.
+     * @param instantiator The MBeanInstantiator that will be used to
+     *        instantiate MBeans and take care of class loading issues.
+     * @param repository The repository to use for this MBeanServer
+     */
+    public NamespaceDispatchInterceptor(MBeanServer         outer,
+                               MBeanServerDelegate delegate,
+                               MBeanInstantiator   instantiator,
+                               Repository          repository)  {
+           localNamespace = new DomainDispatchInterceptor(outer,delegate,
+                   instantiator,repository,this);
+           serverName = Util.getMBeanServerSecurityName(delegate);
+    }
+
+    // TODO: Should move that to JMXNamespace? or to ObjectName?
+    /**
+     * Get first name space in ObjectName path. Ignore leading namespace
+     * separators.
+     **/
+    public static String getFirstNamespace(ObjectName name) {
+        if (name == null) return "";
+        final String domain = name.getDomain();
+        if (domain.equals("")) return "";
+
+        int first = 0;
+        int end = domain.indexOf(NAMESPACE_SEPARATOR,first);
+        while (end == first) {
+            first = end+NAMESPACE_SEPARATOR_LENGTH;
+            end = domain.indexOf(NAMESPACE_SEPARATOR,first);
+            if (end == -1) break;
+        }
+
+        if (end == -1) return "";
+
+        final String namespace = domain.substring(first,end);
+
+        return namespace;
+    }
+
+    /**
+     * Called by the DefaultMBeanServerInterceptor, just before adding an
+     * MBean to the repository.
+     *
+     * @param resource the MBean to be registered.
+     * @param logicalName the name of the MBean to be registered.
+     */
+    final void checkLocallyRegistrable(Object resource,
+            ObjectName logicalName) {
+        if (!(resource instanceof JMXNamespace) &&
+                logicalName.getDomain().contains(NAMESPACE_SEPARATOR))
+            throw new IllegalArgumentException(String.valueOf(logicalName)+
+                    ": Invalid ObjectName for an instance of " +
+                    resource.getClass().getName());
+    }
+
+    final boolean isLocalHandlerNameFor(String namespace,
+            ObjectName handlerName) {
+        return handlerName.getDomain().equals(namespace+NAMESPACE_SEPARATOR) &&
+               JMXNamespace.TYPE_ASSIGNMENT.equals(
+               handlerName.getKeyPropertyListString());
+    }
+
+    @Override
+    final MBeanServer getInterceptorOrNullFor(ObjectName name) {
+        final String namespace = getFirstNamespace(name);
+        if (namespace.equals("") || isLocalHandlerNameFor(namespace,name) ||
+            name.getDomain().equals(namespace+NAMESPACE_SEPARATOR)) {
+            LOG.finer("dispatching to local name space");
+            return localNamespace;
+        }
+        final NamespaceInterceptor ns = getInterceptor(namespace);
+        if (LOG.isLoggable(Level.FINER)) {
+            if (ns != null) {
+                LOG.finer("dispatching to name space: " + namespace);
+            } else {
+                LOG.finer("no handler for: " + namespace);
+            }
+        }
+        return ns;
+    }
+
+    @Override
+    final QueryInterceptor getInterceptorForQuery(ObjectName pattern) {
+        final String namespace = getFirstNamespace(pattern);
+        if (namespace.equals("") || isLocalHandlerNameFor(namespace,pattern) ||
+            pattern.getDomain().equals(namespace+NAMESPACE_SEPARATOR)) {
+            LOG.finer("dispatching to local name space");
+            return new QueryInterceptor(localNamespace);
+        }
+        final NamespaceInterceptor ns = getInterceptor(namespace);
+        if (LOG.isLoggable(Level.FINER)) {
+            if (ns != null) {
+                LOG.finer("dispatching to name space: " + namespace);
+            } else {
+                LOG.finer("no handler for: " + namespace);
+            }
+        }
+        if (ns == null) return null;
+        return new QueryInterceptor(ns);
+    }
+
+    @Override
+    final ObjectName getHandlerNameFor(String key)
+        throws MalformedObjectNameException {
+        return ObjectName.getInstance(key+NAMESPACE_SEPARATOR,
+                    "type", JMXNamespace.TYPE);
+    }
+
+    @Override
+    final public String getHandlerKey(ObjectName name) {
+        return getFirstNamespace(name);
+    }
+
+    @Override
+    final NamespaceInterceptor createInterceptorFor(String key,
+            ObjectName name, JMXNamespace handler,
+            Queue<Runnable> postRegisterQueue) {
+        final NamespaceInterceptor ns =
+                new NamespaceInterceptor(serverName,handler,key);
+        if (LOG.isLoggable(Level.FINER)) {
+            LOG.finer("NamespaceInterceptor created: "+ns);
+        }
+        return ns;
+    }
+
+    @Override
+    final DomainDispatchInterceptor getNextInterceptor() {
+        return localNamespace;
+    }
+
+    /**
+     * Returns the list of domains in which any MBean is currently
+     * registered.
+     */
+    @Override
+    public String[] getDomains() {
+        return localNamespace.getDomains();
+    }
+
+    @Override
+    public void addNamespace(ObjectName name, JMXNamespace handler,
+            Queue<Runnable> postRegisterQueue) {
+        if (handler instanceof JMXDomain)
+            localNamespace.addNamespace(name,
+                    (JMXDomain)handler,postRegisterQueue);
+        else super.addNamespace(name,handler,postRegisterQueue);
+    }
+
+    @Override
+    public void removeNamespace(ObjectName name, JMXNamespace handler,
+            Queue<Runnable> postDeregisterQueue) {
+        if (handler instanceof JMXDomain)
+            localNamespace.removeNamespace(name,(JMXDomain)handler,
+                    postDeregisterQueue);
+        else super.removeNamespace(name,handler,postDeregisterQueue);
+    }
+
+
+}