blob: dfd4e659fd1f0e38bde9f09c2b1ed550f39f1af5 [file] [log] [blame]
/*
* 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);
}
}