| /* |
| * 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); |
| } |
| |
| |
| } |