提交 d0d8afd9 编写于 作者: M michaelm

Merge

......@@ -8,3 +8,5 @@ b6d6877c1155621a175dccd12dc14c54f938fb8b jdk7-b30
b7474b739d13bacd9972f88ac91f6350b7b0be12 jdk7-b31
c51121419e30eac5f0fbbce45ff1711c4ce0de28 jdk7-b32
fa4c0a6cdd25d97d4e6f5d7aa180bcbb0e0d56af jdk7-b33
434055a0716ee44bca712ebca02fc04b20e6e288 jdk7-b34
cf4894b78ceb966326e93bf221db0c2d14d59218 jdk7-b35
......@@ -539,6 +539,8 @@ else
WSCRIPT :=$(call FileExists,$(_WSCRIPT1),$(_WSCRIPT2))
endif
WSCRIPT:=$(call AltCheckSpaces,WSCRIPT)
# batch mode no modal dialogs on errors, please.
WSCRIPT += -B
# CSCRIPT: path to cscript.exe (used in creating install bundles)
ifdef ALT_CSCRIPT
......@@ -561,6 +563,10 @@ else
MSIVAL2 :=$(call FileExists,$(_MSIVAL2_1),$(_MSIVAL2_2))
endif
MSIVAL2:=$(call AltCheckSpaces,MSIVAL2)
# suppress msival2 checks, as it hangs jprt builds
ifdef SKIP_MSIVAL2
MSIVAL2 := $(ECHO)
endif
# LOGOCUB: path to cub file for (used in validating install msi files)
ifdef ALT_LOGOCUB
......
......@@ -55,6 +55,5 @@ jprt.solaris_x64.build.platform.match32=solaris_i586_5.10
jprt.test.targets=*-*-*-jvm98
# Directories needed to build
jprt.bundle.src.dirs=make src
jprt.bundle.exclude.src.dirs=build
......@@ -27,7 +27,6 @@ package com.sun.jmx.event;
import com.sun.jmx.remote.util.ClassLogger;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
......@@ -115,6 +114,7 @@ public class LeaseManager {
scheduled = null;
}
callback.run();
executor.shutdown();
}
}
......@@ -131,6 +131,13 @@ public class LeaseManager {
logger.trace("stop", "canceling lease");
scheduled.cancel(false);
scheduled = null;
try {
executor.shutdown();
} catch (SecurityException e) {
// OK: caller doesn't have RuntimePermission("modifyThread")
// which is unlikely in reality but triggers a test failure otherwise
logger.trace("stop", "exception from executor.shutdown", e);
}
}
private final Runnable callback;
......@@ -138,7 +145,7 @@ public class LeaseManager {
private final ScheduledExecutorService executor
= Executors.newScheduledThreadPool(1,
new DaemonThreadFactory("LeaseManager"));
new DaemonThreadFactory("JMX LeaseManager %d"));
private static final ClassLogger logger =
new ClassLogger("javax.management.event", "LeaseManager");
......
......@@ -95,7 +95,9 @@ public abstract class RepeatedSingletonJob implements Runnable {
executor.execute(this);
} catch (RejectedExecutionException e) {
logger.warning(
"setEventReceiver", "Executor threw exception", e);
"execute",
"Executor threw exception (" + this.getClass().getName() + ")",
e);
throw new RejectedExecutionException(
"Executor.execute threw exception -" +
"should not be possible", e);
......
......@@ -613,8 +613,7 @@ public class DefaultMBeanServerInterceptor
List<String> result = new ArrayList<String>(domains.length);
for (int i = 0; i < domains.length; i++) {
try {
ObjectName dom =
Util.newObjectName(domains[i] + ":x=x");
ObjectName dom = ObjectName.valueOf(domains[i] + ":x=x");
checkMBeanPermission(mbeanServerName, (String) null, null, dom, "getDomains");
result.add(domains[i]);
} catch (SecurityException e) {
......@@ -1170,7 +1169,7 @@ public class DefaultMBeanServerInterceptor
if one is supplied where it shouldn't be). */
final String completeName = domain + name;
return Util.newObjectName(completeName);
return ObjectName.valueOf(completeName);
}
public String getDefaultDomain() {
......@@ -2021,7 +2020,7 @@ public class DefaultMBeanServerInterceptor
private void addJMXNamespace(JMXNamespace namespace,
final ObjectName logicalName,
final Queue<Runnable> postQueue) {
dispatcher.addNamespace(logicalName, namespace, postQueue);
dispatcher.addInterceptorFor(logicalName, namespace, postQueue);
}
/**
......@@ -2035,7 +2034,7 @@ public class DefaultMBeanServerInterceptor
private void removeJMXNamespace(JMXNamespace namespace,
final ObjectName logicalName,
final Queue<Runnable> postQueue) {
dispatcher.removeNamespace(logicalName, namespace, postQueue);
dispatcher.removeInterceptorFor(logicalName, namespace, postQueue);
}
/**
......
......@@ -194,7 +194,7 @@ public abstract class DispatchInterceptor
// found in the handlerMap. Note: there doesn't need to be an interceptor
// for that key in the Map.
//
public abstract String getHandlerKey(ObjectName name);
abstract String getHandlerKey(ObjectName name);
// Returns an interceptor for that name, or null if there's no interceptor
// for that name.
......@@ -277,7 +277,7 @@ public abstract class DispatchInterceptor
// of JMXNamespace (or a subclass of it) is registered as an MBean.
// This method is usually invoked from within the repository lock,
// hence the necessity of the postRegisterQueue.
public void addNamespace(ObjectName name, N jmxNamespace,
public void addInterceptorFor(ObjectName name, N jmxNamespace,
Queue<Runnable> postRegisterQueue) {
final String key = getHandlerKey(name);
validateHandlerNameFor(key,name);
......@@ -298,7 +298,7 @@ public abstract class DispatchInterceptor
// of JMXNamespace (or a subclass of it) is deregistered.
// This method is usually invoked from within the repository lock,
// hence the necessity of the postDeregisterQueue.
public void removeNamespace(ObjectName name, N jmxNamespace,
public void removeInterceptorFor(ObjectName name, N jmxNamespace,
Queue<Runnable> postDeregisterQueue) {
final String key = getHandlerKey(name);
final T ns;
......@@ -330,7 +330,7 @@ public abstract class DispatchInterceptor
}
// From MBeanServer
public ObjectInstance createMBean(String className, ObjectName name)
public final ObjectInstance createMBean(String className, ObjectName name)
throws ReflectionException, InstanceAlreadyExistsException,
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException {
......@@ -338,7 +338,7 @@ public abstract class DispatchInterceptor
}
// From MBeanServer
public ObjectInstance createMBean(String className, ObjectName name,
public final ObjectInstance createMBean(String className, ObjectName name,
ObjectName loaderName)
throws ReflectionException, InstanceAlreadyExistsException,
MBeanRegistrationException, MBeanException,
......@@ -347,7 +347,7 @@ public abstract class DispatchInterceptor
}
// From MBeanServer
public ObjectInstance createMBean(String className, ObjectName name,
public final ObjectInstance createMBean(String className, ObjectName name,
Object params[], String signature[])
throws ReflectionException, InstanceAlreadyExistsException,
MBeanRegistrationException, MBeanException,
......@@ -357,7 +357,7 @@ public abstract class DispatchInterceptor
}
// From MBeanServer
public ObjectInstance createMBean(String className, ObjectName name,
public final ObjectInstance createMBean(String className, ObjectName name,
ObjectName loaderName, Object params[],
String signature[])
throws ReflectionException, InstanceAlreadyExistsException,
......@@ -368,42 +368,43 @@ public abstract class DispatchInterceptor
}
// From MBeanServer
public ObjectInstance registerMBean(Object object, ObjectName name)
public final ObjectInstance registerMBean(Object object, ObjectName name)
throws InstanceAlreadyExistsException, MBeanRegistrationException,
NotCompliantMBeanException {
return getInterceptorForCreate(name).registerMBean(object,name);
}
// From MBeanServer
public void unregisterMBean(ObjectName name)
public final void unregisterMBean(ObjectName name)
throws InstanceNotFoundException, MBeanRegistrationException {
getInterceptorForInstance(name).unregisterMBean(name);
}
// From MBeanServer
public ObjectInstance getObjectInstance(ObjectName name)
public final ObjectInstance getObjectInstance(ObjectName name)
throws InstanceNotFoundException {
return getInterceptorForInstance(name).getObjectInstance(name);
}
// From MBeanServer
public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) {
final QueryInterceptor mbs =
public final Set<ObjectInstance> queryMBeans(ObjectName name,
QueryExp query) {
final QueryInterceptor queryInvoker =
getInterceptorForQuery(name);
if (mbs == null) return Collections.emptySet();
else return mbs.queryMBeans(name,query);
if (queryInvoker == null) return Collections.emptySet();
else return queryInvoker.queryMBeans(name,query);
}
// From MBeanServer
public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
final QueryInterceptor mbs =
public final Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
final QueryInterceptor queryInvoker =
getInterceptorForQuery(name);
if (mbs == null) return Collections.emptySet();
else return mbs.queryNames(name,query);
if (queryInvoker == null) return Collections.emptySet();
else return queryInvoker.queryNames(name,query);
}
// From MBeanServer
public boolean isRegistered(ObjectName name) {
public final boolean isRegistered(ObjectName name) {
final MBeanServer mbs = getInterceptorOrNullFor(name);
if (mbs == null) return false;
else return mbs.isRegistered(name);
......@@ -415,20 +416,21 @@ public abstract class DispatchInterceptor
}
// From MBeanServer
public Object getAttribute(ObjectName name, String attribute)
public final Object getAttribute(ObjectName name, String attribute)
throws MBeanException, AttributeNotFoundException,
InstanceNotFoundException, ReflectionException {
return getInterceptorForInstance(name).getAttribute(name,attribute);
}
// From MBeanServer
public AttributeList getAttributes(ObjectName name, String[] attributes)
public final AttributeList getAttributes(ObjectName name,
String[] attributes)
throws InstanceNotFoundException, ReflectionException {
return getInterceptorForInstance(name).getAttributes(name,attributes);
}
// From MBeanServer
public void setAttribute(ObjectName name, Attribute attribute)
public final void setAttribute(ObjectName name, Attribute attribute)
throws InstanceNotFoundException, AttributeNotFoundException,
InvalidAttributeValueException, MBeanException,
ReflectionException {
......@@ -436,14 +438,14 @@ public abstract class DispatchInterceptor
}
// From MBeanServer
public AttributeList setAttributes(ObjectName name,
public final AttributeList setAttributes(ObjectName name,
AttributeList attributes)
throws InstanceNotFoundException, ReflectionException {
return getInterceptorForInstance(name).setAttributes(name,attributes);
}
// From MBeanServer
public Object invoke(ObjectName name, String operationName,
public final Object invoke(ObjectName name, String operationName,
Object params[], String signature[])
throws InstanceNotFoundException, MBeanException,
ReflectionException {
......@@ -463,63 +465,69 @@ public abstract class DispatchInterceptor
public abstract String[] getDomains();
// From MBeanServer
public void addNotificationListener(ObjectName name,
public final void addNotificationListener(ObjectName name,
NotificationListener listener,
NotificationFilter filter,
Object handback)
throws InstanceNotFoundException {
getInterceptorForInstance(name).addNotificationListener(name,listener,filter,
getInterceptorForInstance(name).
addNotificationListener(name,listener,filter,
handback);
}
// From MBeanServer
public void addNotificationListener(ObjectName name,
public final void addNotificationListener(ObjectName name,
ObjectName listener,
NotificationFilter filter,
Object handback)
throws InstanceNotFoundException {
getInterceptorForInstance(name).addNotificationListener(name,listener,filter,
getInterceptorForInstance(name).
addNotificationListener(name,listener,filter,
handback);
}
// From MBeanServer
public void removeNotificationListener(ObjectName name,
public final void removeNotificationListener(ObjectName name,
ObjectName listener)
throws InstanceNotFoundException, ListenerNotFoundException {
getInterceptorForInstance(name).removeNotificationListener(name,listener);
getInterceptorForInstance(name).
removeNotificationListener(name,listener);
}
// From MBeanServer
public void removeNotificationListener(ObjectName name,
public final void removeNotificationListener(ObjectName name,
ObjectName listener,
NotificationFilter filter,
Object handback)
throws InstanceNotFoundException, ListenerNotFoundException {
getInterceptorForInstance(name).removeNotificationListener(name,listener,filter,
getInterceptorForInstance(name).
removeNotificationListener(name,listener,filter,
handback);
}
// From MBeanServer
public void removeNotificationListener(ObjectName name,
public final void removeNotificationListener(ObjectName name,
NotificationListener listener)
throws InstanceNotFoundException, ListenerNotFoundException {
getInterceptorForInstance(name).removeNotificationListener(name,listener);
getInterceptorForInstance(name).
removeNotificationListener(name,listener);
}
// From MBeanServer
public void removeNotificationListener(ObjectName name,
public final void removeNotificationListener(ObjectName name,
NotificationListener listener,
NotificationFilter filter,
Object handback)
throws InstanceNotFoundException, ListenerNotFoundException {
getInterceptorForInstance(name).removeNotificationListener(name,listener,filter,
getInterceptorForInstance(name).
removeNotificationListener(name,listener,filter,
handback);
}
// From MBeanServer
public MBeanInfo getMBeanInfo(ObjectName name)
public final MBeanInfo getMBeanInfo(ObjectName name)
throws InstanceNotFoundException, IntrospectionException,
ReflectionException {
return getInterceptorForInstance(name).getMBeanInfo(name);
......@@ -527,21 +535,23 @@ public abstract class DispatchInterceptor
// From MBeanServer
public boolean isInstanceOf(ObjectName name, String className)
public final boolean isInstanceOf(ObjectName name, String className)
throws InstanceNotFoundException {
return getInterceptorForInstance(name).isInstanceOf(name,className);
}
// From MBeanServer
public ClassLoader getClassLoaderFor(ObjectName mbeanName)
public final ClassLoader getClassLoaderFor(ObjectName mbeanName)
throws InstanceNotFoundException {
return getInterceptorForInstance(mbeanName).getClassLoaderFor(mbeanName);
return getInterceptorForInstance(mbeanName).
getClassLoaderFor(mbeanName);
}
// From MBeanServer
public ClassLoader getClassLoader(ObjectName loaderName)
public final ClassLoader getClassLoader(ObjectName loaderName)
throws InstanceNotFoundException {
return getInterceptorForInstance(loaderName).getClassLoader(loaderName);
return getInterceptorForInstance(loaderName).
getClassLoader(loaderName);
}
}
......@@ -75,7 +75,7 @@ class DomainDispatchInterceptor
private final DomainDispatchInterceptor parent;
AggregatingQueryInterceptor(DomainDispatchInterceptor dispatcher) {
super(dispatcher.localNamespace);
super(dispatcher.nextInterceptor);
parent = dispatcher;
}
......@@ -91,9 +91,8 @@ class DomainDispatchInterceptor
// Add all matching MBeans from local namespace.
final Set<T> res = Util.cloneSet(local);
final boolean all = (pattern == null ||
pattern.getDomain().equals("*"));
if (pattern == null) pattern = ObjectName.WILDCARD;
final boolean all = pattern.getDomain().equals("*");
final String domain = pattern.getDomain();
......@@ -142,7 +141,7 @@ class DomainDispatchInterceptor
}
}
private final DefaultMBeanServerInterceptor localNamespace;
private final DefaultMBeanServerInterceptor nextInterceptor;
private final String mbeanServerName;
private final MBeanServerDelegate delegate;
......@@ -165,7 +164,7 @@ class DomainDispatchInterceptor
MBeanInstantiator instantiator,
Repository repository,
NamespaceDispatchInterceptor namespaces) {
localNamespace = new DefaultMBeanServerInterceptor(outer,
nextInterceptor = new DefaultMBeanServerInterceptor(outer,
delegate, instantiator,repository,namespaces);
mbeanServerName = Util.getMBeanServerSecurityName(delegate);
this.delegate = delegate;
......@@ -182,7 +181,7 @@ class DomainDispatchInterceptor
@Override
void validateHandlerNameFor(String key, ObjectName name) {
super.validateHandlerNameFor(key,name);
final String[] domains = localNamespace.getDomains();
final String[] domains = nextInterceptor.getDomains();
for (int i=0;i<domains.length;i++) {
if (domains[i].equals(key))
throw new IllegalArgumentException("domain "+key+
......@@ -192,37 +191,72 @@ class DomainDispatchInterceptor
@Override
final MBeanServer getInterceptorOrNullFor(ObjectName name) {
if (name == null) return localNamespace;
if (name == null) return nextInterceptor;
final String domain = name.getDomain();
if (domain.endsWith(NAMESPACE_SEPARATOR)) return localNamespace;
if (domain.contains(NAMESPACE_SEPARATOR)) return null;
final String localDomain = domain;
if (isLocalHandlerNameFor(localDomain,name)) {
if (domain.endsWith(NAMESPACE_SEPARATOR))
return nextInterceptor; // This can be a namespace handler.
if (domain.contains(NAMESPACE_SEPARATOR))
return null; // shouldn't reach here.
if (isLocalHandlerNameFor(domain,name)) {
// This is the name of a JMXDomain MBean. Return nextInterceptor.
LOG.finer("dispatching to local namespace");
return localNamespace;
return nextInterceptor;
}
final DomainInterceptor ns = getInterceptor(localDomain);
final DomainInterceptor ns = getInterceptor(domain);
if (ns == null) {
// no JMXDomain found for that domain - return nextInterceptor.
if (LOG.isLoggable(Level.FINER)) {
LOG.finer("dispatching to local namespace: " + localDomain);
LOG.finer("dispatching to local namespace: " + domain);
}
return getNextInterceptor();
}
if (LOG.isLoggable(Level.FINER)) {
LOG.finer("dispatching to domain: " + localDomain);
LOG.finer("dispatching to domain: " + domain);
}
return ns;
}
// This method returns true if the given pattern must be evaluated against
// several interceptors. This happens when either:
//
// a) the pattern can select several domains (it's null, or it's a
// domain pattern)
// or b) it's not a domain pattern, but it might select the name of a
// JMXDomain MBean in charge of that domain. Since the JMXDomain
// MBean is located in the nextInterceptor, the pattern might need
// to be evaluated on two interceptors.
//
// 1. When this method returns false, the query is evaluated on a single
// interceptor:
// The interceptor for pattern.getDomain(), if there is one,
// or the next interceptor, if there is none.
//
// 2. When this method returns true, we loop over all the domain
// interceptors:
// in the list, and if the domain pattern matches the interceptor domain
// we evaluate the query on that interceptor and aggregate the results.
// Eventually we also evaluate the pattern against the next interceptor.
//
// See getInterceptorForQuery below.
//
private boolean multipleQuery(ObjectName pattern) {
// case a) above
if (pattern == null) return true;
if (pattern.isDomainPattern()) return true;
try {
// case b) above.
//
// This is a bit of a hack. If there's any chance that a JMXDomain
// MBean name is selected by the given pattern then we must include
// the local namespace in our search.
// Returning true will have this effect.
//
// Returning true will have this effect. see 2. above.
//
if (pattern.apply(ALL_DOMAINS.withDomain(pattern.getDomain())))
return true;
} catch (MalformedObjectNameException x) {
......@@ -253,7 +287,7 @@ class DomainDispatchInterceptor
// We don't have a virtual domain. Send to local domains.
if (LOG.isLoggable(Level.FINER))
LOG.finer("dispatching to local namespace: " + domain);
return new QueryInterceptor(localNamespace);
return new QueryInterceptor(nextInterceptor);
}
@Override
......@@ -288,7 +322,7 @@ class DomainDispatchInterceptor
@Override
final DefaultMBeanServerInterceptor getNextInterceptor() {
return localNamespace;
return nextInterceptor;
}
/**
......@@ -298,11 +332,11 @@ class DomainDispatchInterceptor
@Override
public String[] getDomains() {
// A JMXDomain is registered in its own domain.
// Therefore, localNamespace.getDomains() contains all domains.
// In addition, localNamespace will perform the necessary
// Therefore, nextInterceptor.getDomains() contains all domains.
// In addition, nextInterceptor will perform the necessary
// MBeanPermission checks for getDomains().
//
return localNamespace.getDomains();
return nextInterceptor.getDomains();
}
/**
......@@ -310,13 +344,13 @@ class DomainDispatchInterceptor
*/
@Override
public Integer getMBeanCount() {
int count = getNextInterceptor().getMBeanCount().intValue();
int count = getNextInterceptor().getMBeanCount();
final String[] keys = getKeys();
for (String key:keys) {
final MBeanServer mbs = getInterceptor(key);
if (mbs == null) continue;
count += mbs.getMBeanCount().intValue();
count += mbs.getMBeanCount();
}
return Integer.valueOf(count);
return count;
}
}
......@@ -61,7 +61,7 @@ public class NamespaceDispatchInterceptor
private static final int NAMESPACE_SEPARATOR_LENGTH =
NAMESPACE_SEPARATOR.length();
private final DomainDispatchInterceptor localNamespace;
private final DomainDispatchInterceptor nextInterceptor;
private final String serverName;
/**
......@@ -84,7 +84,7 @@ public class NamespaceDispatchInterceptor
MBeanServerDelegate delegate,
MBeanInstantiator instantiator,
Repository repository) {
localNamespace = new DomainDispatchInterceptor(outer,delegate,
nextInterceptor = new DomainDispatchInterceptor(outer,delegate,
instantiator,repository,this);
serverName = Util.getMBeanServerSecurityName(delegate);
}
......@@ -94,21 +94,21 @@ public class NamespaceDispatchInterceptor
* Get first name space in ObjectName path. Ignore leading namespace
* separators.
**/
public static String getFirstNamespace(ObjectName name) {
static String getFirstNamespace(ObjectName name) {
if (name == null) return "";
final String domain = name.getDomain();
if (domain.equals("")) return "";
// skip leading separators
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;
}
while (domain.startsWith(NAMESPACE_SEPARATOR,first))
first += NAMESPACE_SEPARATOR_LENGTH;
if (end == -1) return "";
// go to next separator
final int end = domain.indexOf(NAMESPACE_SEPARATOR,first);
if (end == -1) return ""; // no namespace
// This is the first element in the namespace path.
final String namespace = domain.substring(first,end);
return namespace;
......@@ -143,7 +143,7 @@ public class NamespaceDispatchInterceptor
if (namespace.equals("") || isLocalHandlerNameFor(namespace,name) ||
name.getDomain().equals(namespace+NAMESPACE_SEPARATOR)) {
LOG.finer("dispatching to local name space");
return localNamespace;
return nextInterceptor;
}
final NamespaceInterceptor ns = getInterceptor(namespace);
if (LOG.isLoggable(Level.FINER)) {
......@@ -162,7 +162,7 @@ public class NamespaceDispatchInterceptor
if (namespace.equals("") || isLocalHandlerNameFor(namespace,pattern) ||
pattern.getDomain().equals(namespace+NAMESPACE_SEPARATOR)) {
LOG.finer("dispatching to local name space");
return new QueryInterceptor(localNamespace);
return new QueryInterceptor(nextInterceptor);
}
final NamespaceInterceptor ns = getInterceptor(namespace);
if (LOG.isLoggable(Level.FINER)) {
......@@ -202,7 +202,7 @@ public class NamespaceDispatchInterceptor
@Override
final DomainDispatchInterceptor getNextInterceptor() {
return localNamespace;
return nextInterceptor;
}
/**
......@@ -211,25 +211,25 @@ public class NamespaceDispatchInterceptor
*/
@Override
public String[] getDomains() {
return localNamespace.getDomains();
return nextInterceptor.getDomains();
}
@Override
public void addNamespace(ObjectName name, JMXNamespace handler,
public void addInterceptorFor(ObjectName name, JMXNamespace handler,
Queue<Runnable> postRegisterQueue) {
if (handler instanceof JMXDomain)
localNamespace.addNamespace(name,
nextInterceptor.addInterceptorFor(name,
(JMXDomain)handler,postRegisterQueue);
else super.addNamespace(name,handler,postRegisterQueue);
else super.addInterceptorFor(name,handler,postRegisterQueue);
}
@Override
public void removeNamespace(ObjectName name, JMXNamespace handler,
public void removeInterceptorFor(ObjectName name, JMXNamespace handler,
Queue<Runnable> postDeregisterQueue) {
if (handler instanceof JMXDomain)
localNamespace.removeNamespace(name,(JMXDomain)handler,
nextInterceptor.removeInterceptorFor(name,(JMXDomain)handler,
postDeregisterQueue);
else super.removeNamespace(name,handler,postDeregisterQueue);
else super.removeInterceptorFor(name,handler,postDeregisterQueue);
}
......
......@@ -1172,10 +1172,10 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
final Class<ConstructorProperties> propertyNamesClass = ConstructorProperties.class;
Class targetClass = getTargetClass();
Constructor[] constrs = targetClass.getConstructors();
Constructor<?>[] constrs = targetClass.getConstructors();
// Applicable if and only if there are any annotated constructors
List<Constructor> annotatedConstrList = newList();
List<Constructor<?>> annotatedConstrList = newList();
for (Constructor<?> constr : constrs) {
if (Modifier.isPublic(constr.getModifiers())
&& constr.getAnnotation(propertyNamesClass) != null)
......@@ -1206,7 +1206,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
// Also remember the set of properties in that constructor
// so we can test unambiguity.
Set<BitSet> getterIndexSets = newSet();
for (Constructor constr : annotatedConstrList) {
for (Constructor<?> constr : annotatedConstrList) {
String[] propertyNames =
constr.getAnnotation(propertyNamesClass).value();
......@@ -1363,10 +1363,10 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
}
private static class Constr {
final Constructor constructor;
final Constructor<?> constructor;
final int[] paramIndexes;
final BitSet presentParams;
Constr(Constructor constructor, int[] paramIndexes,
Constr(Constructor<?> constructor, int[] paramIndexes,
BitSet presentParams) {
this.constructor = constructor;
this.paramIndexes = paramIndexes;
......
......@@ -623,7 +623,7 @@ abstract class MBeanIntrospector<M> {
}
private static MBeanConstructorInfo[] findConstructors(Class<?> c) {
Constructor[] cons = c.getConstructors();
Constructor<?>[] cons = c.getConstructors();
MBeanConstructorInfo[] mbc = new MBeanConstructorInfo[cons.length];
for (int i = 0; i < cons.length; i++) {
String descr = "Public constructor of the MBean";
......
......@@ -396,7 +396,7 @@ public class Repository {
// Set domain to default if domain is empty and not already set
if (dom.length() == 0)
name = Util.newObjectName(domain + name.toString());
name = ObjectName.valueOf(domain + name.toString());
// Do we have default domain ?
if (dom == domain) { // ES: OK (dom & domain are interned)
......
......@@ -57,7 +57,8 @@ import static javax.management.namespace.JMXNamespaces.NAMESPACE_SEPARATOR;
public class Util {
private final static int NAMESPACE_SEPARATOR_LENGTH =
NAMESPACE_SEPARATOR.length();
public final static String ILLEGAL_MBEANSERVER_NAME_CHARS=";:*?";
public final static char[] ILLEGAL_MBEANSERVER_NAME_CHARS=";:*?".
toCharArray();
static <K, V> Map<K, V> newMap() {
......@@ -109,14 +110,6 @@ public class Util {
return new ArrayList<E>(c);
}
public static ObjectName newObjectName(String s) {
try {
return new ObjectName(s);
} catch (MalformedObjectNameException e) {
throw new IllegalArgumentException(e);
}
}
/* This method can be used by code that is deliberately violating the
* allowed checked casts. Rather than marking the whole method containing
* the code with @SuppressWarnings, you can use a call to this method for
......@@ -621,7 +614,7 @@ public class Util {
* is {@code null}.
* @throws IllegalArgumentException if mbeanServerName contains illegal
* characters, or is empty, or is {@code "-"}.
* Illegal characters are {@value #ILLEGAL_MBEANSERVER_NAME_CHARS}.
* Illegal characters are {@link #ILLEGAL_MBEANSERVER_NAME_CHARS}.
*/
public static String checkServerName(String mbeanServerName) {
if ("".equals(mbeanServerName))
......@@ -632,7 +625,7 @@ public class Util {
"\"-\" is not a valid MBean server name");
if (isMBeanServerNameUndefined(mbeanServerName))
return MBeanServerFactory.DEFAULT_MBEANSERVER_NAME;
for (char c : ILLEGAL_MBEANSERVER_NAME_CHARS.toCharArray()) {
for (char c : ILLEGAL_MBEANSERVER_NAME_CHARS) {
if (mbeanServerName.indexOf(c) >= 0)
throw new IllegalArgumentException(
"invalid character in MBeanServer name: "+c);
......@@ -662,15 +655,15 @@ public class Util {
}
// Log the exception and its causes without logging the stack trace.
// Use with care - it is usally preferable to log the whole stack trace!
// Use with care - it is usually preferable to log the whole stack trace!
// We don't want to log the whole stack trace here: logshort() is
// called in those cases where the exception might not be abnormal.
private static void logshort(String msg, Throwable t) {
if (JmxProperties.MISC_LOGGER.isLoggable(Level.FINE)) {
StringBuilder toprint = new StringBuilder(msg);
toprint.append("\nCaused By: ").append(String.valueOf(t));
while ((t=t.getCause())!=null)
toprint.append("\nCaused By: ").append(String.valueOf(t));
do {
toprint.append("\nCaused By: ").append(String.valueOf(t));
} while ((t=t.getCause())!=null);
JmxProperties.MISC_LOGGER.fine(toprint.toString());
}
}
......
......@@ -85,7 +85,7 @@ public class DomainInterceptor extends HandlerInterceptor<JMXDomain> {
final ObjectName pattern;
public PatternNotificationFilter(ObjectName pattern) {
this.pattern = pattern;
this.pattern = pattern==null?ObjectName.WILDCARD:pattern;
}
public boolean isNotificationEnabled(Notification notification) {
......@@ -93,7 +93,7 @@ public class DomainInterceptor extends HandlerInterceptor<JMXDomain> {
return false;
final MBeanServerNotification mbsn =
(MBeanServerNotification) notification;
if (pattern == null || pattern.apply(mbsn.getMBeanName()))
if (pattern.apply(mbsn.getMBeanName()))
return true;
return false;
}
......@@ -110,6 +110,7 @@ public class DomainInterceptor extends HandlerInterceptor<JMXDomain> {
super(handler);
this.domainName = domainName;
this.serverName = serverName;
ALL = ObjectName.valueOf(domainName+":*");
}
@Override
......@@ -118,27 +119,27 @@ public class DomainInterceptor extends HandlerInterceptor<JMXDomain> {
", domain="+this.domainName+")";
}
public void connectDelegate(final MBeanServerDelegate delegate)
final void connectDelegate(final MBeanServerDelegate delegate)
throws InstanceNotFoundException {
final NotificationFilter filter =
new PatternNotificationFilter(getPatternFor(null));
synchronized (this) {
if (mbsListener == null)
if (mbsListener == null) {
mbsListener = new NotificationListener() {
public void handleNotification(Notification notification,
Object handback) {
if (filter.isNotificationEnabled(notification))
delegate.sendNotification(notification);
}
};
public void handleNotification(Notification notification,
Object handback) {
if (filter.isNotificationEnabled(notification))
delegate.sendNotification(notification);
}
};
}
}
getNamespace().
getHandlerInterceptorMBean().
addMBeanServerNotificationListener(mbsListener, filter);
}
public void disconnectDelegate()
final void disconnectDelegate()
throws InstanceNotFoundException, ListenerNotFoundException {
final NotificationListener l;
synchronized (this) {
......@@ -146,10 +147,10 @@ public class DomainInterceptor extends HandlerInterceptor<JMXDomain> {
if (l == null) return;
mbsListener = null;
}
getNamespace().removeMBeanServerNotificationListener(l);
getHandlerInterceptorMBean().removeMBeanServerNotificationListener(l);
}
public void addPostRegisterTask(Queue<Runnable> queue,
public final void addPostRegisterTask(Queue<Runnable> queue,
final MBeanServerDelegate delegate) {
if (queue == null)
throw new IllegalArgumentException("task queue must not be null");
......@@ -158,14 +159,15 @@ public class DomainInterceptor extends HandlerInterceptor<JMXDomain> {
try {
connectDelegate(delegate);
} catch (Exception x) {
throw new UnsupportedOperationException("notification forwarding",x);
throw new UnsupportedOperationException(
"notification forwarding",x);
}
}
};
queue.add(task1);
}
public void addPostDeregisterTask(Queue<Runnable> queue,
public final void addPostDeregisterTask(Queue<Runnable> queue,
final MBeanServerDelegate delegate) {
if (queue == null)
throw new IllegalArgumentException("task queue must not be null");
......@@ -174,17 +176,18 @@ public class DomainInterceptor extends HandlerInterceptor<JMXDomain> {
try {
disconnectDelegate();
} catch (Exception x) {
throw new UnsupportedOperationException("notification forwarding",x);
throw new UnsupportedOperationException(
"notification forwarding",x);
}
}
};
queue.add(task1);
}
/**
* Throws IllegalArgumentException if targetName.getDomain() is not
* in the domain handled.
**/
// No name conversion for JMXDomains...
// Throws IllegalArgumentException if targetName.getDomain() is not
// in the domain handled.
//
@Override
protected ObjectName toSource(ObjectName targetName) {
if (targetName == null) return null;
......@@ -198,6 +201,7 @@ public class DomainInterceptor extends HandlerInterceptor<JMXDomain> {
return targetName;
}
// No name conversion for JMXDomains...
@Override
protected ObjectName toTarget(ObjectName sourceName) {
return sourceName;
......@@ -255,16 +259,16 @@ public class DomainInterceptor extends HandlerInterceptor<JMXDomain> {
if (LOG.isLoggable(Level.FINE))
LOG.fine("Unexpected exception raised in queryNames: "+x);
LOG.log(Level.FINEST,"Unexpected exception raised in queryNames",x);
return Collections.emptySet();
}
// We reach here only when an exception was raised.
//
final Set<ObjectName> empty = Collections.emptySet();
return empty;
}
// Compute a new pattern which is a sub pattern of 'name' but only selects
// the MBeans in domain 'domainName'
// When we reach here, it has been verified that 'name' matches our domain
// name (done by DomainDispatchInterceptor)
private ObjectName getPatternFor(final ObjectName name) {
try {
if (ALL == null) ALL = ObjectName.getInstance(domainName + ":*");
if (name == null) return ALL;
if (name.getDomain().equals(domainName)) return name;
return name.withDomain(domainName);
......@@ -284,11 +288,8 @@ public class DomainInterceptor extends HandlerInterceptor<JMXDomain> {
if (LOG.isLoggable(Level.FINE))
LOG.fine("Unexpected exception raised in queryNames: "+x);
LOG.log(Level.FINEST,"Unexpected exception raised in queryNames",x);
return Collections.emptySet();
}
// We reach here only when an exception was raised.
//
final Set<ObjectInstance> empty = Collections.emptySet();
return empty;
}
@Override
......@@ -306,7 +307,7 @@ public class DomainInterceptor extends HandlerInterceptor<JMXDomain> {
// in the domain.
@Override
public Integer getMBeanCount() {
return getNamespace().getMBeanCount();
return getHandlerInterceptorMBean().getMBeanCount();
}
private boolean checkOn() {
......@@ -320,8 +321,8 @@ public class DomainInterceptor extends HandlerInterceptor<JMXDomain> {
@Override
void check(ObjectName routingName, String member, String action) {
if (!checkOn()) return;
final String act = (action==null)?"-":action.intern();
if(act == "queryMBeans" || act == "queryNames") { // ES: OK
final String act = (action==null)?"-":action;
if("queryMBeans".equals(act) || "queryNames".equals(act)) {
// This is tricky. check with 3 parameters is called
// by queryNames/queryMBeans before performing the query.
// At this point we must check with no class name.
......@@ -355,16 +356,8 @@ public class DomainInterceptor extends HandlerInterceptor<JMXDomain> {
if (!checkOn()) return;
final MBeanPermission perm;
// action is most probably already an intern string.
// string literals are intern strings.
// we create a new intern string for 'action' - just to be on
// the safe side...
// We intern it in order to be able to use == rather than equals
// below, because if we don't, and if action is not one of the
// 4 literals below, we would have to do a full string comparison.
//
final String act = (action==null)?"-":action.intern();
if (act == "getDomains") { // ES: OK
final String act = (action==null)?"-":action;
if ("getDomains".equals(act)) { // ES: OK
perm = new MBeanPermission(serverName,"-",member,
routingName,act);
} else {
......@@ -381,7 +374,7 @@ public class DomainInterceptor extends HandlerInterceptor<JMXDomain> {
String getClassName(ObjectName routingName) {
if (routingName == null || routingName.isPattern()) return "-";
try {
return getNamespace().getSourceServer().
return getHandlerInterceptorMBean().getSourceServer().
getObjectInstance(routingName).getClassName();
} catch (InstanceNotFoundException ex) {
LOG.finest("Can't get class name for "+routingName+
......@@ -444,7 +437,7 @@ public class DomainInterceptor extends HandlerInterceptor<JMXDomain> {
int count=0;
for (int i=0;i<domains.length;i++) {
try {
check(Util.newObjectName(domains[i]+":x=x"),"-",
check(ObjectName.valueOf(domains[i]+":x=x"),"-",
"-","getDomains");
} catch (SecurityException x) { // DLS: OK
count++;
......
......@@ -29,7 +29,6 @@ import com.sun.jmx.defaults.JmxProperties;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.logging.Level;
......@@ -40,6 +39,8 @@ import javax.management.MBeanServerConnection;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.event.EventClient;
import javax.management.event.EventClientDelegateMBean;
import javax.management.namespace.JMXNamespace;
import javax.management.namespace.JMXNamespaces;
import javax.management.remote.JMXAddressable;
import javax.management.remote.JMXConnector;
......@@ -66,26 +67,10 @@ public final class JMXNamespaceUtils {
return new WeakHashMap<K,V>();
}
/** Creates a new instance of JMXNamespaces */
/** There are no instances of this class */
private JMXNamespaceUtils() {
}
/**
* Returns an unmodifiable option map in which the given keys have been
* filtered out.
* @param keys keys to filter out from the map.
* @return An unmodifiable option map in which the given keys have been
* filtered out.
*/
public static <K,V> Map<K,V> filterMap(Map<K,V> map, K... keys) {
final Map<K,V> filtered;
filtered=new HashMap<K,V>(map);
for (K key : keys) {
filtered.remove(key);
}
return unmodifiableMap(filtered);
}
// returns un unmodifiable view of a map.
public static <K,V> Map<K,V> unmodifiableMap(Map<K,V> aMap) {
if (aMap == null || aMap.isEmpty())
......
......@@ -25,22 +25,15 @@
package com.sun.jmx.namespace;
import com.sun.jmx.defaults.JmxProperties;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Logger;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.MBeanServer;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.QueryExp;
import javax.management.namespace.JMXNamespaces;
import javax.management.namespace.JMXNamespace;
import javax.management.namespace.JMXNamespacePermission;
......@@ -54,12 +47,6 @@ import javax.management.namespace.JMXNamespacePermission;
*/
public class NamespaceInterceptor extends HandlerInterceptor<JMXNamespace> {
/**
* A logger for this class.
**/
private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER;
private static final Logger PROBE_LOG = Logger.getLogger(
JmxProperties.NAMESPACE_LOGGER+".probe");
// The target name space in which the NamepsaceHandler is mounted.
private final String targetNs;
......@@ -68,21 +55,6 @@ public class NamespaceInterceptor extends HandlerInterceptor<JMXNamespace> {
private final ObjectNameRouter proc;
/**
* Internal hack. The JMXRemoteNamespace can be closed and reconnected.
* Each time the JMXRemoteNamespace connects, a probe should be sent
* to detect cycle. The MBeanServer exposed by JMXRemoteNamespace thus
* implements the DynamicProbe interface, which makes it possible for
* this handler to know that it should send a new probe.
*
* XXX: TODO this probe thing is way too complex and fragile.
* This *must* go away or be replaced by something simpler.
* ideas are welcomed.
**/
public static interface DynamicProbe {
public boolean isProbeRequested();
}
/**
* Creates a new instance of NamespaceInterceptor
*/
......@@ -104,164 +76,6 @@ public class NamespaceInterceptor extends HandlerInterceptor<JMXNamespace> {
", namespace="+this.targetNs+")";
}
/*
* XXX: TODO this probe thing is way too complex and fragile.
* This *must* go away or be replaced by something simpler.
* ideas are welcomed.
*/
private volatile boolean probed = false;
private volatile ObjectName probe;
// Query Pattern that we will send through the source server in order
// to detect self-linking namespaces.
//
// XXX: TODO this probe thing is way too complex and fragile.
// This *must* go away or be replaced by something simpler.
// ideas are welcomed.
final ObjectName makeProbePattern(ObjectName probe)
throws MalformedObjectNameException {
// we could probably link the probe pattern with the probe - e.g.
// using the UUID as key in the pattern - but is it worth it? it
// also has some side effects on the context namespace - because
// such a probe may get rejected by the jmx.context// namespace.
//
// The trick here is to devise a pattern that is not likely to
// be blocked by intermediate levels. Querying for all namespace
// handlers in the source (or source namespace) is more likely to
// achieve this goal.
//
return ObjectName.getInstance("*" +
JMXNamespaces.NAMESPACE_SEPARATOR + ":" +
JMXNamespace.TYPE_ASSIGNMENT);
}
// tell whether the name pattern corresponds to what might have been
// sent as a probe.
// XXX: TODO this probe thing is way too complex and fragile.
// This *must* go away or be replaced by something simpler.
// ideas are welcomed.
final boolean isProbePattern(ObjectName name) {
final ObjectName p = probe;
if (p == null) return false;
try {
return String.valueOf(name).endsWith(targetNs+
JMXNamespaces.NAMESPACE_SEPARATOR + "*" +
JMXNamespaces.NAMESPACE_SEPARATOR + ":" +
JMXNamespace.TYPE_ASSIGNMENT);
} catch (RuntimeException x) {
// should not happen.
PROBE_LOG.finest("Ignoring unexpected exception in self link detection: "+
x);
return false;
}
}
// The first time a request reaches this NamespaceInterceptor, the
// interceptor will send a probe to detect whether the underlying
// JMXNamespace links to itslef.
//
// One way to create such self-linking namespace would be for instance
// to create a JMXNamespace whose getSourceServer() method would return:
// JMXNamespaces.narrowToNamespace(getMBeanServer(),
// getObjectName().getDomain())
//
// If such an MBeanServer is returned, then any call to that MBeanServer
// will trigger an infinite loop.
// There can be even trickier configurations if remote connections are
// involved.
//
// In order to prevent this from happening, the NamespaceInterceptor will
// send a probe, in an attempt to detect whether it will receive it at
// the other end. If the probe is received, an exception will be thrown
// in order to break the recursion. The probe is only sent once - when
// the first request to the namespace occurs. The DynamicProbe interface
// can also be used by a Sun JMXNamespace implementation to request the
// emission of a probe at any time (see JMXRemoteNamespace
// implementation).
//
// Probes work this way: the NamespaceInterceptor sets a flag and sends
// a queryNames() request. If a queryNames() request comes in when the flag
// is on, then it deduces that there is a self-linking loop - and instead
// of calling queryNames() on the source MBeanServer of the JMXNamespace
// handler (which would cause the loop to go on) it breaks the recursion
// by returning the probe ObjectName.
// If the NamespaceInterceptor receives the probe ObjectName as result of
// its original sendProbe() request it knows that it has been looping
// back on itslef and throws an IOException...
//
//
// XXX: TODO this probe thing is way too complex and fragile.
// This *must* go away or be replaced by something simpler.
// ideas are welcomed.
//
final void sendProbe(MBeanServerConnection msc)
throws IOException {
try {
PROBE_LOG.fine("Sending probe");
// This is just to prevent any other thread to modify
// the probe while the detection cycle is in progress.
//
final ObjectName probePattern;
// we don't want to synchronize on this - we use targetNs
// because it's non null and final.
synchronized (targetNs) {
probed = false;
if (probe != null) {
throw new IOException("concurent connection in progress");
}
final String uuid = UUID.randomUUID().toString();
final String endprobe =
JMXNamespaces.NAMESPACE_SEPARATOR + uuid +
":type=Probe,key="+uuid;
final ObjectName newprobe =
ObjectName.getInstance(endprobe);
probePattern = makeProbePattern(newprobe);
probe = newprobe;
}
try {
PROBE_LOG.finer("Probe query: "+probePattern+" expecting: "+probe);
final Set<ObjectName> res = msc.queryNames(probePattern, null);
final ObjectName expected = probe;
PROBE_LOG.finer("Probe res: "+res);
if (res.contains(expected)) {
throw new IOException("namespace " +
targetNs + " is linking to itself: " +
"cycle detected by probe");
}
} catch (SecurityException x) {
PROBE_LOG.finer("Can't check for cycles: " + x);
// can't do anything....
} catch (RuntimeException x) {
PROBE_LOG.finer("Exception raised by queryNames: " + x);
throw x;
} finally {
probe = null;
}
} catch (MalformedObjectNameException x) {
final IOException io =
new IOException("invalid name space: probe failed");
io.initCause(x);
throw io;
}
PROBE_LOG.fine("Probe returned - no cycles");
probed = true;
}
// allows a Sun implementation JMX Namespace, such as the
// JMXRemoteNamespace, to control when a probe should be sent.
//
// XXX: TODO this probe thing is way too complex and fragile.
// This *must* go away or be replaced by something simpler.
// ideas are welcomed.
private boolean isProbeRequested(Object o) {
if (o instanceof DynamicProbe)
return ((DynamicProbe)o).isProbeRequested();
return false;
}
/**
* This method will send a probe to detect self-linking name spaces.
* A self linking namespace is a namespace that links back directly
......@@ -281,29 +95,9 @@ public class NamespaceInterceptor extends HandlerInterceptor<JMXNamespace> {
* (see JMXRemoteNamespace implementation).
*/
private MBeanServer connection() {
try {
final MBeanServer c = super.source();
if (probe != null) // should not happen
throw new RuntimeException("connection is being probed");
if (probed == false || isProbeRequested(c)) {
try {
// Should not happen if class well behaved.
// Never probed. Force it.
//System.err.println("sending probe for " +
// "target="+targetNs+", source="+srcNs);
sendProbe(c);
} catch (IOException io) {
throw new RuntimeException(io.getMessage(), io);
}
}
if (c != null) {
return c;
}
} catch (RuntimeException x) {
throw x;
}
final MBeanServer c = super.source();
if (c != null) return c;
// should not come here
throw new NullPointerException("getMBeanServerConnection");
}
......@@ -319,24 +113,6 @@ public class NamespaceInterceptor extends HandlerInterceptor<JMXNamespace> {
return super.source();
}
/**
* Calls {@link MBeanServerConnection#queryNames queryNames}
* on the underlying
* {@link #getMBeanServerConnection MBeanServerConnection}.
**/
@Override
public final Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
// XXX: TODO this probe thing is way too complex and fragile.
// This *must* go away or be replaced by something simpler.
// ideas are welcomed.
PROBE_LOG.finer("probe is: "+probe+" pattern is: "+name);
if (probe != null && isProbePattern(name)) {
PROBE_LOG.finer("Return probe: "+probe);
return Collections.singleton(probe);
}
return super.queryNames(name, query);
}
@Override
protected ObjectName toSource(ObjectName targetName)
throws MalformedObjectNameException {
......
......@@ -45,6 +45,9 @@ import javax.management.namespace.JMXNamespaces;
* </b></p>
* @since 1.7
*/
// See class hierarchy and detailled explanations in RoutingProxy in this
// package.
//
public class RoutingConnectionProxy
extends RoutingProxy<MBeanServerConnection> {
......@@ -93,40 +96,28 @@ public class RoutingConnectionProxy
targetNs+"\", "+forwardsContext+")";
}
static final RoutingProxyFactory
<MBeanServerConnection,RoutingConnectionProxy>
FACTORY = new RoutingProxyFactory
<MBeanServerConnection,RoutingConnectionProxy>() {
public RoutingConnectionProxy newInstance(MBeanServerConnection source,
String sourcePath, String targetPath,
boolean forwardsContext) {
return new RoutingConnectionProxy(source,sourcePath,
targetPath,forwardsContext);
}
public RoutingConnectionProxy newInstance(
MBeanServerConnection source, String sourcePath) {
return new RoutingConnectionProxy(source,sourcePath);
}
};
public static MBeanServerConnection cd(MBeanServerConnection source,
String sourcePath) {
if (source == null) throw new IllegalArgumentException("null");
if (source.getClass().equals(RoutingConnectionProxy.class)) {
// cast is OK here, but findbugs complains unless we use class.cast
final RoutingConnectionProxy other =
RoutingConnectionProxy.class.cast(source);
final String target = other.getTargetNamespace();
// Avoid multiple layers of serialization.
//
// We construct a new proxy from the original source instead of
// stacking a new proxy on top of the old one.
// - that is we replace
// cd ( cd ( x, dir1), dir2);
// by
// cd (x, dir1//dir2);
//
// We can do this only when the source class is exactly
// NamespaceConnectionProxy.
//
if (target == null || target.equals("")) {
final String path =
JMXNamespaces.concat(other.getSourceNamespace(),
sourcePath);
return new RoutingConnectionProxy(other.source(),path,"",
other.forwardsContext);
}
// Note: we could do possibly something here - but it would involve
// removing part of targetDir, and possibly adding
// something to sourcePath.
// Too complex to bother! => simply default to stacking...
}
return new RoutingConnectionProxy(source,sourcePath);
return RoutingProxy.cd(RoutingConnectionProxy.class, FACTORY,
source, sourcePath);
}
}
......@@ -83,18 +83,32 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
}
/**
* Returns the wrapped source connection.
* Returns the wrapped source connection. The {@code source} connection
* is a connection to the MBeanServer that contains the actual MBean.
* In the case of cascading, that would be a connection to the sub
* agent.
**/
protected abstract T source() throws IOException;
/**
* Converts a target ObjectName to a source ObjectName.
* The target ObjectName is the name of the MBean in the mount point
* target. In the case of cascading, that would be the name of the
* MBean in the master agent. So if a subagent S containing an MBean
* named "X" is mounted in the target namespace "foo//" of a master agent M,
* the source is S, the target is "foo//" in M, the source name is "X", and
* the target name is "foo//X".
* In the case of cascading - such as in NamespaceInterceptor, this method
* will convert "foo//X" (the targetName) into "X", the source name.
**/
protected abstract ObjectName toSource(ObjectName targetName)
throws MalformedObjectNameException;
/**
* Converts a source ObjectName to a target ObjectName.
* (see description of toSource above for explanations)
* In the case of cascading - such as in NamespaceInterceptor, this method
* will convert "X" (the sourceName) into "foo//X", the target name.
**/
protected abstract ObjectName toTarget(ObjectName sourceName)
throws MalformedObjectNameException;
......@@ -142,90 +156,17 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
return new RuntimeOperationsException(x2);
}
/**
* This method is a hook to implement permission checking in subclasses.
* By default, this method does nothing and simply returns
* {@code attribute}.
*
* @param routingName The name of the MBean in the enclosing context.
* This is of the form {@code <namespace>//<ObjectName>}.
* @param attributes The list of attributes to check permission for.
* @param action one of "getAttribute" or "setAttribute"
* @return The list of attributes for which the callers has the
* appropriate {@link
* javax.management.namespace.JMXNamespacePermission}.
*/
String[] checkAttributes(ObjectName routingName,
String[] attributes, String action) {
check(routingName,null,action);
return attributes;
}
/**
* This method is a hook to implement permission checking in subclasses.
* By default, this method does nothing and simply returns
* {@code attribute}.
*
* @param routingName The name of the MBean in the enclosing context.
* This is of the form {@code <namespace>//<ObjectName>}.
* @param attributes The list of attributes to check permission for.
* @param action one of "getAttribute" or "setAttribute"
* @return The list of attributes for which the callers has the
* appropriate {@link
* javax.management.namespace.JMXNamespacePermission}.
*/
AttributeList checkAttributes(ObjectName routingName,
AttributeList attributes, String action) {
check(routingName,null,action);
return attributes;
}
// from MBeanServerConnection
public AttributeList getAttributes(ObjectName name, String[] attributes)
throws InstanceNotFoundException, ReflectionException, IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
final String[] authorized =
checkAttributes(name,attributes,"getAttribute");
final AttributeList attrList =
source().getAttributes(sourceName,authorized);
return attrList;
return source().getAttributes(sourceName, attributes);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
/**
* This method is a hook to implement permission checking in subclasses.
* By default, this method does nothing.
* A subclass may override this method and throw a {@link
* SecurityException} if the permission is denied.
*
* @param routingName The name of the MBean in the enclosing context.
* This is of the form {@code <namespace>//<ObjectName>}.
* @param member The {@link
* javax.management.namespace.JMXNamespacePermission#getMember member}
* name.
* @param action The {@link
* javax.management.namespace.JMXNamespacePermission#getActions action}
* name.
*/
void check(ObjectName routingName,
String member, String action) {
}
void checkPattern(ObjectName routingPattern,
String member, String action) {
// pattern is checked only at posteriori by checkQuery.
// checking it a priori usually doesn't work, because ObjectName.apply
// does not work between two patterns.
check(null,null,action);
}
void checkCreate(ObjectName routingName, String className,
String action) {
}
// from MBeanServerConnection
public Object invoke(ObjectName name, String operationName, Object[] params,
String[] signature)
......@@ -233,7 +174,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
check(name, operationName, "invoke");
final Object result =
source().invoke(sourceName,operationName,params,
signature);
......@@ -249,7 +189,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
check(name, null, "unregisterMBean");
source().unregisterMBean(sourceName);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
......@@ -262,7 +201,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
ReflectionException, IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
check(name, null, "getMBeanInfo");
return source().getMBeanInfo(sourceName);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
......@@ -274,7 +212,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
throws InstanceNotFoundException, IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
check(name, null, "getObjectInstance");
return processOutputInstance(
source().getObjectInstance(sourceName));
} catch (RuntimeException ex) {
......@@ -301,9 +238,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
ReflectionException, IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
check(name,
(attribute==null?null:attribute.getName()),
"setAttribute");
source().setAttribute(sourceName,attribute);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
......@@ -321,8 +255,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
// Loader Name is already a sourceLoaderName.
final ObjectName sourceLoaderName = loaderName;
try {
checkCreate(name, className, "instantiate");
checkCreate(name, className, "registerMBean");
final ObjectInstance instance =
source().createMBean(className,sourceName,
sourceLoaderName,
......@@ -341,8 +273,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
NotCompliantMBeanException, IOException {
final ObjectName sourceName = newSourceMBeanName(name);
try {
checkCreate(name, className, "instantiate");
checkCreate(name, className, "registerMBean");
return processOutputInstance(source().createMBean(className,
sourceName,params,signature));
} catch (RuntimeException ex) {
......@@ -360,8 +290,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
// Loader Name is already a source Loader Name.
final ObjectName sourceLoaderName = loaderName;
try {
checkCreate(name, className, "instantiate");
checkCreate(name, className, "registerMBean");
return processOutputInstance(source().createMBean(className,
sourceName,sourceLoaderName));
} catch (RuntimeException ex) {
......@@ -376,8 +304,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
NotCompliantMBeanException, IOException {
final ObjectName sourceName = newSourceMBeanName(name);
try {
checkCreate(name, className, "instantiate");
checkCreate(name, className, "registerMBean");
return processOutputInstance(source().
createMBean(className,sourceName));
} catch (RuntimeException ex) {
......@@ -391,7 +317,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
InstanceNotFoundException, ReflectionException, IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
check(name, attribute, "getAttribute");
return source().getAttribute(sourceName,attribute);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
......@@ -403,7 +328,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
throws InstanceNotFoundException, IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
check(name, null, "isInstanceOf");
return source().isInstanceOf(sourceName,className);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
......@@ -415,10 +339,8 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
throws InstanceNotFoundException, ReflectionException, IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
final AttributeList authorized =
checkAttributes(name, attributes, "setAttribute");
return source().
setAttributes(sourceName,authorized);
setAttributes(sourceName,attributes);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
......@@ -431,7 +353,7 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
for (ObjectInstance i : sources) {
try {
final ObjectInstance target = processOutputInstance(i);
if (!checkQuery(target.getObjectName(), "queryMBeans"))
if (excludesFromResult(target.getObjectName(), "queryMBeans"))
continue;
result.add(target);
} catch (Exception x) {
......@@ -446,24 +368,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
return result;
}
/**
* This is a hook to implement permission checking in subclasses.
*
* Checks that the caller has sufficient permission for returning
* information about {@code sourceName} in {@code action}.
*
* By default always return true. Subclass may override this method
* and return false if the caller doesn't have sufficient permissions.
*
* @param routingName The name of the MBean to include or exclude from
* the query, expressed in the enclosing context.
* This is of the form {@code <namespace>//<ObjectName>}.
* @param action one of "queryNames" or "queryMBeans"
* @return true if {@code sourceName} can be returned.
*/
boolean checkQuery(ObjectName routingName, String action) {
return true;
}
// Return names in the target's context.
ObjectInstance processOutputInstance(ObjectInstance source) {
......@@ -488,7 +392,7 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
for (ObjectName n : sourceNames) {
try {
final ObjectName targetName = toTarget(n);
if (!checkQuery(targetName, "queryNames")) continue;
if (excludesFromResult(targetName, "queryNames")) continue;
names.add(targetName);
} catch (Exception x) {
if (LOG.isLoggable(Level.FINE)) {
......@@ -508,7 +412,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
if (name == null) name=ObjectName.WILDCARD;
final ObjectName sourceName = toSourceOrRuntime(name);
try {
checkPattern(name,null,"queryMBeans");
return processOutputInstances(
source().queryMBeans(sourceName,query));
} catch (RuntimeException ex) {
......@@ -523,7 +426,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
if (name == null) name=ObjectName.WILDCARD;
final ObjectName sourceName = toSourceOrRuntime(name);
try {
checkPattern(name,null,"queryNames");
final Set<ObjectName> tmp = source().queryNames(sourceName,query);
final Set<ObjectName> out = processOutputNames(tmp);
//System.err.println("queryNames: out: "+out);
......@@ -540,7 +442,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
ListenerNotFoundException, IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
check(name,null,"removeNotificationListener");
source().removeNotificationListener(sourceName,listener);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
......@@ -554,7 +455,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
final ObjectName sourceName = toSourceOrRuntime(name);
// Listener name is already a source listener name.
try {
check(name,null,"addNotificationListener");
source().addNotificationListener(sourceName,listener,
filter,handback);
} catch (RuntimeException ex) {
......@@ -568,7 +468,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
Object handback) throws InstanceNotFoundException, IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
check(name,null,"addNotificationListener");
source().addNotificationListener(sourceName, listener, filter,
handback);
} catch (RuntimeException ex) {
......@@ -585,7 +484,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
check(name,null,"removeNotificationListener");
source().removeNotificationListener(sourceName,listener,filter,
handback);
} catch (RuntimeException ex) {
......@@ -600,7 +498,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
check(name,null,"removeNotificationListener");
source().removeNotificationListener(sourceName,listener,
filter,handback);
} catch (RuntimeException ex) {
......@@ -616,7 +513,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
// listener name is already a source name...
final ObjectName sourceListener = listener;
try {
check(name,null,"removeNotificationListener");
source().removeNotificationListener(sourceName,sourceListener);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
......@@ -635,30 +531,12 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
// from MBeanServerConnection
public String[] getDomains() throws IOException {
try {
check(null,null,"getDomains");
final String[] domains = source().getDomains();
return checkDomains(domains,"getDomains");
return source().getDomains();
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
/**
* This method is a hook to implement permission checking in subclasses.
* Checks that the caller as the necessary permissions to view the
* given domain. If not remove the domains for which the caller doesn't
* have permission from the list.
* <p>
* By default, this method always returns {@code domains}
*
* @param domains The domains to return.
* @param action "getDomains"
* @return a filtered list of domains.
*/
String[] checkDomains(String[] domains, String action) {
return domains;
}
// from MBeanServerConnection
public String getDefaultDomain() throws IOException {
try {
......@@ -668,4 +546,22 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
}
}
/**
* Returns true if the given targetName must be excluded from the
* query result.
* In this base class, always return {@code false}.
* By default all object names returned by the sources are
* transmitted to the caller - there is no filtering.
*
* @param name A target object name expressed in the caller's
* context. In the case of cascading, where the source
* is a sub agent mounted on e.g. namespace "foo",
* that would be a name prefixed by "foo//"...
* @param queryMethod either "queryNames" or "queryMBeans".
* @return true if the name must be excluded.
*/
boolean excludesFromResult(ObjectName targetName, String queryMethod) {
return false;
}
}
......@@ -30,31 +30,110 @@ import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.namespace.JMXNamespaces;
/**
* An RoutingProxy narrows on a given name space in a
* A RoutingProxy narrows on a given name space in a
* source object implementing MBeanServerConnection.
* It is used to implement
* {@code JMXNamespaces.narrowToNamespace(...)}.
* This abstract class has two concrete subclasses:
* <p>{@link RoutingConnectionProxy}: to cd in an MBeanServerConnection.</p>
* <p>{@link RoutingServerProxy}: to cd in an MBeanServer.</p>
* <p>{@link RoutingConnectionProxy}: to narrow down into an
* MBeanServerConnection.</p>
* <p>{@link RoutingServerProxy}: to narrow down into an MBeanServer.</p>
*
* <p>This class can also be used to "broaden" from a namespace. The same
* class is used for both purposes because in both cases all that happens
* is that ObjectNames are rewritten in one way on the way in (e.g. the
* parameter of getMBeanInfo) and another way on the way out (e.g. the
* return value of queryNames).</p>
*
* <p>Specifically, if you narrow into "a//" then you want to add the
* "a//" prefix to ObjectNames on the way in and subtract it on the way
* out. But ClientContext uses this class to subtract the
* "jmx.context//foo=bar//" prefix on the way in and add it back on the
* way out.</p>
*
* <p><b>
* This API is a Sun internal API and is subject to changes without notice.
* </b></p>
* @since 1.7
*/
//
// RoutingProxies are client side objects which are used to narrow down
// into a namespace. They are used to perform ObjectName translation,
// adding the namespace to the routing ObjectName before sending it over
// to the source connection, and removing that prefix from results of
// queries, createMBean, registerMBean, and getObjectInstance.
// This translation is the opposite to that which is performed by
// NamespaceInterceptors.
//
// There is however a special case where routing proxies are used on the
// 'server' side to remove a namespace - rather than to add it:
// This the case of ClientContext.
// When an ObjectName like "jmx.context//c1=v1,c2=v2//D:k=v" reaches the
// jmx.context namespace, a routing proxy is used to remove the prefix
// c1=v1,c2=v2// from the routing objectname.
//
// For a RoutingProxy used in a narrowDownToNamespace operation, we have:
// targetNs="" // targetNS is the namespace 'to remove'
// sourceNS=<namespace-we-narrow-down-to> // namespace 'to add'
//
// For a RoutingProxy used in a ClientContext operation, we have:
// targetNs=<encoded-context> // context must be removed from object name
// sourceNs="" // nothing to add...
//
// RoutingProxies can also be used on the client side to implement
// "withClientContext" operations. In that case, the boolean parameter
// 'forwards context' is set to true, targetNs is "", and sourceNS may
// also be "". When forwardsContext is true, the RoutingProxy dynamically
// creates an ObjectNameRouter for each operation - in order to dynamically add
// the context attached to the thread to the routing ObjectName. This is
// performed in the getObjectNameRouter() method.
//
// Finally, in order to avoid too many layers of wrapping,
// RoutingConnectionProxy and RoutingServerProxy can be created through a
// factory method that can concatenate namespace pathes in order to
// return a single RoutingProxy - rather than wrapping a RoutingProxy inside
// another RoutingProxy. See RoutingConnectionProxy.cd and
// RoutingServerProxy.cd
//
// The class hierarchy is as follows:
//
// RoutingMBeanServerConnection
// [abstract class for all routing interceptors,
// such as RoutingProxies and HandlerInterceptors]
// / \
// / \
// RoutingProxy HandlerInterceptor
// [base class for [base class for server side
// client-side objects used objects, created by
// in narrowDownTo] DispatchInterceptors]
// / \ | \
// RoutingConnectionProxy \ | NamespaceInterceptor
// [wraps MBeanServerConnection \ | [used to remove
// objects] \ | namespace prefix and
// RoutingServerProxy | wrap JMXNamespace]
// [wraps MBeanServer |
// Objects] |
// DomainInterceptor
// [used to wrap JMXDomain]
//
// RoutingProxies also differ from HandlerInterceptors in that they transform
// calls to MBeanServerConnection operations that do not have any parameters
// into a call to the underlying JMXNamespace MBean.
// So for instance a call to:
// JMXNamespaces.narrowDownToNamespace(conn,"foo").getDomains()
// is transformed into
// conn.getAttribute("foo//type=JMXNamespace","Domains");
//
public abstract class RoutingProxy<T extends MBeanServerConnection>
extends RoutingMBeanServerConnection<T> {
......@@ -179,17 +258,11 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
throw x;
} catch (MBeanException ex) {
throw new IOException("Failed to get "+attributeName+": "+
ex.getMessage(),
ex.getTargetException());
} catch (AttributeNotFoundException ex) {
throw new IOException("Failed to get "+attributeName+": "+
ex.getMessage(),ex);
} catch (InstanceNotFoundException ex) {
ex.getCause(),
ex.getCause());
} catch (Exception ex) {
throw new IOException("Failed to get "+attributeName+": "+
ex.getMessage(),ex);
} catch (ReflectionException ex) {
throw new IOException("Failed to get "+attributeName+": "+
ex.getMessage(),ex);
ex,ex);
}
}
......@@ -279,4 +352,62 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
(" mounted on targetNs="+targetNs));
}
// Creates an instance of a subclass 'R' of RoutingProxy<T>
// RoutingServerProxy and RoutingConnectionProxy have their own factory
// instance.
static interface RoutingProxyFactory<T extends MBeanServerConnection,
R extends RoutingProxy<T>> {
R newInstance(T source,
String sourcePath, String targetPath,
boolean forwardsContext);
R newInstance(T source,
String sourcePath);
}
// Performs a narrowDownToNamespace operation.
// This method will attempt to merge two RoutingProxies in a single
// one if they are of the same class.
//
// This method is never called directly - it should be called only by
// subclasses of RoutingProxy.
//
// As for now it is called by:
// RoutingServerProxy.cd and RoutingConnectionProxy.cd.
//
static <T extends MBeanServerConnection, R extends RoutingProxy<T>>
R cd(Class<R> routingProxyClass,
RoutingProxyFactory<T,R> factory,
T source, String sourcePath) {
if (source == null) throw new IllegalArgumentException("null");
if (source.getClass().equals(routingProxyClass)) {
// cast is OK here, but findbugs complains unless we use class.cast
final R other = routingProxyClass.cast(source);
final String target = other.getTargetNamespace();
// Avoid multiple layers of serialization.
//
// We construct a new proxy from the original source instead of
// stacking a new proxy on top of the old one.
// - that is we replace
// cd ( cd ( x, dir1), dir2);
// by
// cd (x, dir1//dir2);
//
// We can do this only when the source class is exactly
// RoutingServerProxy.
//
if (target == null || target.equals("")) {
final String path =
JMXNamespaces.concat(other.getSourceNamespace(),
sourcePath);
return factory.newInstance(other.source(),path,"",
other.forwardsContext);
}
// Note: we could do possibly something here - but it would involve
// removing part of targetDir, and possibly adding
// something to sourcePath.
// Too complex to bother! => simply default to stacking...
}
return factory.newInstance(source,sourcePath);
}
}
......@@ -69,6 +69,9 @@ import javax.management.namespace.JMXNamespaces;
*
* @since 1.7
*/
// See class hierarchy and detailled explanations in RoutingProxy in this
// package.
//
public class RoutingServerProxy
extends RoutingProxy<MBeanServer>
implements MBeanServer {
......@@ -564,39 +567,24 @@ public class RoutingServerProxy
}
}
static final RoutingProxyFactory<MBeanServer,RoutingServerProxy>
FACTORY = new RoutingProxyFactory<MBeanServer,RoutingServerProxy>() {
public RoutingServerProxy newInstance(MBeanServer source,
String sourcePath, String targetPath,
boolean forwardsContext) {
return new RoutingServerProxy(source,sourcePath,
targetPath,forwardsContext);
}
public RoutingServerProxy newInstance(
MBeanServer source, String sourcePath) {
return new RoutingServerProxy(source,sourcePath);
}
};
public static MBeanServer cd(MBeanServer source, String sourcePath) {
if (source == null) throw new IllegalArgumentException("null");
if (source.getClass().equals(RoutingServerProxy.class)) {
// cast is OK here, but findbugs complains unless we use class.cast
final RoutingServerProxy other =
RoutingServerProxy.class.cast(source);
final String target = other.getTargetNamespace();
// Avoid multiple layers of serialization.
//
// We construct a new proxy from the original source instead of
// stacking a new proxy on top of the old one.
// - that is we replace
// cd ( cd ( x, dir1), dir2);
// by
// cd (x, dir1//dir2);
//
// We can do this only when the source class is exactly
// NamespaceServerProxy.
//
if (target == null || target.equals("")) {
final String path =
JMXNamespaces.concat(other.getSourceNamespace(),
sourcePath);
return new RoutingServerProxy(other.source(),path,"",
other.forwardsContext);
}
// Note: we could do possibly something here - but it would involve
// removing part of targetDir, and possibly adding
// something to sourcePath.
// Too complex to bother! => simply default to stacking...
}
return new RoutingServerProxy(source,sourcePath);
return RoutingProxy.cd(RoutingServerProxy.class, FACTORY,
source, sourcePath);
}
}
......@@ -32,13 +32,15 @@ import com.sun.jmx.remote.util.ClassLogger;
import com.sun.jmx.remote.util.EnvHelp;
public abstract class ClientCommunicatorAdmin {
private static volatile long threadNo = 1;
public ClientCommunicatorAdmin(long period) {
this.period = period;
if (period > 0) {
checker = new Checker();
Thread t = new Thread(checker);
Thread t = new Thread(checker, "JMX client heartbeat " + ++threadNo);
t.setDaemon(true);
t.start();
} else
......
/*
* Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1998-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
......@@ -256,13 +256,13 @@ public class ExtCheck {
private boolean isNotOlderThan(String already,String target)
throws NumberFormatException
{
if (already == null || already.length() < 1) {
if (already == null || already.length() < 1) {
throw new NumberFormatException("Empty version string");
}
// Until it matches scan and compare numbers
StringTokenizer dtok = new StringTokenizer(target, ".", true);
StringTokenizer stok = new StringTokenizer(already, ".", true);
// Until it matches scan and compare numbers
StringTokenizer dtok = new StringTokenizer(target, ".", true);
StringTokenizer stok = new StringTokenizer(already, ".", true);
while (dtok.hasMoreTokens() || stok.hasMoreTokens()) {
int dver;
int sver;
......@@ -276,19 +276,19 @@ public class ExtCheck {
} else
sver = 0;
if (sver < dver)
return false; // Known to be incompatible
if (sver > dver)
return true; // Known to be compatible
// Check for and absorb separators
if (dtok.hasMoreTokens())
dtok.nextToken();
if (stok.hasMoreTokens())
stok.nextToken();
// Compare next component
}
// All components numerically equal
if (sver < dver)
return false; // Known to be incompatible
if (sver > dver)
return true; // Known to be compatible
// Check for and absorb separators
if (dtok.hasMoreTokens())
dtok.nextToken();
if (stok.hasMoreTokens())
stok.nextToken();
// Compare next component
}
// All components numerically equal
return true;
}
......@@ -307,11 +307,10 @@ public class ExtCheck {
}
/**
* Print out the error message and exit from the program
* Throws a RuntimeException with a message describing the error.
*/
static void error(String message){
System.err.println(message);
System.exit(-1);
static void error(String message) throws RuntimeException {
throw new RuntimeException(message);
}
......@@ -356,19 +355,19 @@ public class ExtCheck {
}
private JarFile findJarFile(URL url) throws IOException {
// Optimize case where url refers to a local jar file
if ("file".equals(url.getProtocol())) {
String path = url.getFile().replace('/', File.separatorChar);
File file = new File(path);
if (!file.exists()) {
throw new FileNotFoundException(path);
}
return new JarFile(path);
}
URLConnection uc = getBaseURL().openConnection();
//uc.setRequestProperty(USER_AGENT_JAVA_VERSION, JAVA_VERSION);
return ((JarURLConnection)uc).getJarFile();
}
// Optimize case where url refers to a local jar file
if ("file".equals(url.getProtocol())) {
String path = url.getFile().replace('/', File.separatorChar);
File file = new File(path);
if (!file.exists()) {
throw new FileNotFoundException(path);
}
return new JarFile(path);
}
URLConnection uc = getBaseURL().openConnection();
//uc.setRequestProperty(USER_AGENT_JAVA_VERSION, JAVA_VERSION);
return ((JarURLConnection)uc).getJarFile();
}
/*
......
/*
* Copyright 1998 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1998-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
......@@ -32,7 +32,10 @@ import java.io.*;
*/
public final class Main {
public static final String INSUFFICIENT = "Insufficient number of arguments";
public static final String MISSING = "Missing <jar file> argument";
public static final String DOES_NOT_EXIST = "Jarfile does not exist: ";
public static final String EXTRA = "Extra command line argument: ";
/**
* Terminates with one of the following codes
......@@ -40,26 +43,36 @@ public final class Main {
* 0 No newer jar file was found
* -1 An internal error occurred
*/
public static void main(String args[]){
if (args.length < 1){
System.err.println("Usage: extcheck [-verbose] <jar file>");
public static void main(String args[]) {
try {
realMain(args);
} catch (Exception ex) {
System.err.println(ex.getMessage());
System.exit(-1);
}
}
public static void realMain(String[] args) throws Exception {
if (args.length < 1) {
usage(INSUFFICIENT);
}
int argIndex = 0;
boolean verboseFlag = false;
if (args[argIndex].equals("-verbose")){
if (args[argIndex].equals("-verbose")) {
verboseFlag = true;
argIndex++;
if (argIndex >= args.length) {
usage(MISSING);
}
}
String jarName = args[argIndex];
argIndex++;
File jarFile = new File(jarName);
if (!jarFile.exists()){
ExtCheck.error("Jarfile " + jarName + " does not exist");
usage(DOES_NOT_EXIST + jarName);
}
if (argIndex < args.length) {
ExtCheck.error("Extra command line argument :"+args[argIndex]);
usage(EXTRA + args[argIndex]);
}
ExtCheck jt = ExtCheck.create(jarFile,verboseFlag);
boolean result = jt.checkInstalledAgainstTarget();
......@@ -68,7 +81,10 @@ public final class Main {
} else {
System.exit(1);
}
}
private static void usage(String msg) throws Exception {
throw new Exception(msg + "\nUsage: extcheck [-verbose] <jar file>");
}
}
......@@ -212,7 +212,7 @@ package java.lang;
* @throws NullPointerException {@inheritDoc}
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public synchronized void getChars(int srcBegin, int srcEnd, char dst[],
public synchronized void getChars(int srcBegin, int srcEnd, char[] dst,
int dstBegin)
{
super.getChars(srcBegin, srcEnd, dst, dstBegin);
......@@ -228,10 +228,6 @@ package java.lang;
value[index] = ch;
}
/**
* @see java.lang.String#valueOf(java.lang.Object)
* @see #append(java.lang.String)
*/
public synchronized StringBuffer append(Object obj) {
super.append(String.valueOf(obj));
return this;
......@@ -314,20 +310,19 @@ package java.lang;
return this;
}
public synchronized StringBuffer append(char str[]) {
public synchronized StringBuffer append(char[] str) {
super.append(str);
return this;
}
public synchronized StringBuffer append(char str[], int offset, int len) {
/**
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public synchronized StringBuffer append(char[] str, int offset, int len) {
super.append(str, offset, len);
return this;
}
/**
* @see java.lang.String#valueOf(boolean)
* @see #append(java.lang.String)
*/
public synchronized StringBuffer append(boolean b) {
super.append(b);
return this;
......@@ -338,10 +333,6 @@ package java.lang;
return this;
}
/**
* @see java.lang.String#valueOf(int)
* @see #append(java.lang.String)
*/
public synchronized StringBuffer append(int i) {
super.append(i);
return this;
......@@ -355,28 +346,16 @@ package java.lang;
return this;
}
/**
* @see java.lang.String#valueOf(long)
* @see #append(java.lang.String)
*/
public synchronized StringBuffer append(long lng) {
super.append(lng);
return this;
}
/**
* @see java.lang.String#valueOf(float)
* @see #append(java.lang.String)
*/
public synchronized StringBuffer append(float f) {
super.append(f);
return this;
}
/**
* @see java.lang.String#valueOf(double)
* @see #append(java.lang.String)
*/
public synchronized StringBuffer append(double d) {
super.append(d);
return this;
......@@ -437,7 +416,7 @@ package java.lang;
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @since 1.2
*/
public synchronized StringBuffer insert(int index, char str[], int offset,
public synchronized StringBuffer insert(int index, char[] str, int offset,
int len)
{
super.insert(index, str, offset, len);
......@@ -446,9 +425,6 @@ package java.lang;
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @see java.lang.String#valueOf(java.lang.Object)
* @see #insert(int, java.lang.String)
* @see #length()
*/
public synchronized StringBuffer insert(int offset, Object obj) {
super.insert(offset, String.valueOf(obj));
......@@ -457,7 +433,6 @@ package java.lang;
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @see #length()
*/
public synchronized StringBuffer insert(int offset, String str) {
super.insert(offset, str);
......@@ -467,7 +442,7 @@ package java.lang;
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
public synchronized StringBuffer insert(int offset, char str[]) {
public synchronized StringBuffer insert(int offset, char[] str) {
super.insert(offset, str);
return this;
}
......@@ -498,9 +473,6 @@ package java.lang;
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @see java.lang.String#valueOf(boolean)
* @see #insert(int, java.lang.String)
* @see #length()
*/
public StringBuffer insert(int offset, boolean b) {
return insert(offset, String.valueOf(b));
......@@ -508,7 +480,6 @@ package java.lang;
/**
* @throws IndexOutOfBoundsException {@inheritDoc}
* @see #length()
*/
public synchronized StringBuffer insert(int offset, char c) {
super.insert(offset, c);
......@@ -517,9 +488,6 @@ package java.lang;
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @see java.lang.String#valueOf(int)
* @see #insert(int, java.lang.String)
* @see #length()
*/
public StringBuffer insert(int offset, int i) {
return insert(offset, String.valueOf(i));
......@@ -527,9 +495,6 @@ package java.lang;
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @see java.lang.String#valueOf(long)
* @see #insert(int, java.lang.String)
* @see #length()
*/
public StringBuffer insert(int offset, long l) {
return insert(offset, String.valueOf(l));
......@@ -537,9 +502,6 @@ package java.lang;
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @see java.lang.String#valueOf(float)
* @see #insert(int, java.lang.String)
* @see #length()
*/
public StringBuffer insert(int offset, float f) {
return insert(offset, String.valueOf(f));
......@@ -547,9 +509,6 @@ package java.lang;
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @see java.lang.String#valueOf(double)
* @see #insert(int, java.lang.String)
* @see #length()
*/
public StringBuffer insert(int offset, double d) {
return insert(offset, String.valueOf(d));
......
......@@ -124,10 +124,6 @@ public final class StringBuilder
append(seq);
}
/**
* @see java.lang.String#valueOf(java.lang.Object)
* @see #append(java.lang.String)
*/
public StringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
......@@ -175,7 +171,6 @@ public final class StringBuilder
}
/**
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public StringBuilder append(CharSequence s) {
if (s == null)
......@@ -197,20 +192,19 @@ public final class StringBuilder
return this;
}
public StringBuilder append(char str[]) {
public StringBuilder append(char[] str) {
super.append(str);
return this;
}
public StringBuilder append(char str[], int offset, int len) {
/**
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public StringBuilder append(char[] str, int offset, int len) {
super.append(str, offset, len);
return this;
}
/**
* @see java.lang.String#valueOf(boolean)
* @see #append(java.lang.String)
*/
public StringBuilder append(boolean b) {
super.append(b);
return this;
......@@ -221,37 +215,21 @@ public final class StringBuilder
return this;
}
/**
* @see java.lang.String#valueOf(int)
* @see #append(java.lang.String)
*/
public StringBuilder append(int i) {
super.append(i);
return this;
}
/**
* @see java.lang.String#valueOf(long)
* @see #append(java.lang.String)
*/
public StringBuilder append(long lng) {
super.append(lng);
return this;
}
/**
* @see java.lang.String#valueOf(float)
* @see #append(java.lang.String)
*/
public StringBuilder append(float f) {
super.append(f);
return this;
}
/**
* @see java.lang.String#valueOf(double)
* @see #append(java.lang.String)
*/
public StringBuilder append(double d) {
super.append(d);
return this;
......@@ -292,7 +270,7 @@ public final class StringBuilder
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
public StringBuilder insert(int index, char str[], int offset,
public StringBuilder insert(int index, char[] str, int offset,
int len)
{
super.insert(index, str, offset, len);
......@@ -301,9 +279,6 @@ public final class StringBuilder
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @see java.lang.String#valueOf(java.lang.Object)
* @see #insert(int, java.lang.String)
* @see #length()
*/
public StringBuilder insert(int offset, Object obj) {
return insert(offset, String.valueOf(obj));
......@@ -311,7 +286,6 @@ public final class StringBuilder
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @see #length()
*/
public StringBuilder insert(int offset, String str) {
super.insert(offset, str);
......@@ -321,7 +295,7 @@ public final class StringBuilder
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
public StringBuilder insert(int offset, char str[]) {
public StringBuilder insert(int offset, char[] str) {
super.insert(offset, str);
return this;
}
......@@ -349,9 +323,6 @@ public final class StringBuilder
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @see java.lang.String#valueOf(boolean)
* @see #insert(int, java.lang.String)
* @see #length()
*/
public StringBuilder insert(int offset, boolean b) {
super.insert(offset, b);
......@@ -360,7 +331,6 @@ public final class StringBuilder
/**
* @throws IndexOutOfBoundsException {@inheritDoc}
* @see #length()
*/
public StringBuilder insert(int offset, char c) {
super.insert(offset, c);
......@@ -369,9 +339,6 @@ public final class StringBuilder
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @see java.lang.String#valueOf(int)
* @see #insert(int, java.lang.String)
* @see #length()
*/
public StringBuilder insert(int offset, int i) {
return insert(offset, String.valueOf(i));
......@@ -379,9 +346,6 @@ public final class StringBuilder
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @see java.lang.String#valueOf(long)
* @see #insert(int, java.lang.String)
* @see #length()
*/
public StringBuilder insert(int offset, long l) {
return insert(offset, String.valueOf(l));
......@@ -389,9 +353,6 @@ public final class StringBuilder
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @see java.lang.String#valueOf(float)
* @see #insert(int, java.lang.String)
* @see #length()
*/
public StringBuilder insert(int offset, float f) {
return insert(offset, String.valueOf(f));
......@@ -399,9 +360,6 @@ public final class StringBuilder
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @see java.lang.String#valueOf(double)
* @see #insert(int, java.lang.String)
* @see #length()
*/
public StringBuilder insert(int offset, double d) {
return insert(offset, String.valueOf(d));
......
......@@ -388,7 +388,7 @@ enum PlatformComponent {
// if there are more than 1 key properties (i.e. other than "type")
domainAndType += ",*";
}
ObjectName on = com.sun.jmx.mbeanserver.Util.newObjectName(domainAndType);
ObjectName on = ObjectName.valueOf(domainAndType);
Set<ObjectName> set = mbs.queryNames(on, null);
for (PlatformComponent pc : subComponents) {
set.addAll(pc.getObjectNames(mbs));
......
......@@ -186,7 +186,7 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private
// --- Methods to support CharSequence ---
public CharSequence subSequence(int start, int end) {
public CharBuffer subSequence(int start, int end) {
int pos = position();
int lim = limit();
assert (pos <= lim);
......
......@@ -402,7 +402,7 @@ class Direct$Type$Buffer$RW$$BO$
// --- Methods to support CharSequence ---
public CharSequence subSequence(int start, int end) {
public CharBuffer subSequence(int start, int end) {
int pos = position();
int lim = limit();
assert (pos <= lim);
......
......@@ -566,7 +566,7 @@ class Heap$Type$Buffer$RW$
// --- Methods to support CharSequence ---
public CharSequence subSequence(int start, int end) {
public CharBuffer subSequence(int start, int end) {
if ((start < 0)
|| (end > length())
|| (start > end))
......
......@@ -99,7 +99,7 @@ class StringCharBuffer // package-private
return str.toString().substring(start + offset, end + offset);
}
public final CharSequence subSequence(int start, int end) {
public final CharBuffer subSequence(int start, int end) {
try {
int pos = position();
return new StringCharBuffer(str, -1,
......
......@@ -1239,13 +1239,13 @@ public abstract class $Type$Buffer
* smaller than <tt>start</tt> and no larger than
* <tt>remaining()</tt>
*
* @return The new character sequence
* @return The new character buffer
*
* @throws IndexOutOfBoundsException
* If the preconditions on <tt>start</tt> and <tt>end</tt>
* do not hold
*/
public abstract CharSequence subSequence(int start, int end);
public abstract CharBuffer subSequence(int start, int end);
// --- Methods to support Appendable ---
......
/*
* Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2000-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
......@@ -25,6 +25,9 @@
package java.security.cert;
import java.io.InvalidObjectException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.security.GeneralSecurityException;
/**
......@@ -36,10 +39,11 @@ import java.security.GeneralSecurityException;
* if any, that caused this exception to be thrown.
* <p>
* A <code>CertPathValidatorException</code> may also include the
* certification path that was being validated when the exception was thrown
* and the index of the certificate in the certification path that caused the
* exception to be thrown. Use the {@link #getCertPath getCertPath} and
* {@link #getIndex getIndex} methods to retrieve this information.
* certification path that was being validated when the exception was thrown,
* the index of the certificate in the certification path that caused the
* exception to be thrown, and the reason that caused the failure. Use the
* {@link #getCertPath getCertPath}, {@link #getIndex getIndex}, and
* {@link #getReason getReason} methods to retrieve this information.
*
* <p>
* <b>Concurrent Access</b>
......@@ -71,12 +75,17 @@ public class CertPathValidatorException extends GeneralSecurityException {
*/
private CertPath certPath;
/**
* @serial the reason the validation failed
*/
private Reason reason = BasicReason.UNSPECIFIED;
/**
* Creates a <code>CertPathValidatorException</code> with
* no detail message.
*/
public CertPathValidatorException() {
super();
this(null, null);
}
/**
......@@ -87,7 +96,7 @@ public class CertPathValidatorException extends GeneralSecurityException {
* @param msg the detail message
*/
public CertPathValidatorException(String msg) {
super(msg);
this(msg, null);
}
/**
......@@ -104,7 +113,7 @@ public class CertPathValidatorException extends GeneralSecurityException {
* permitted, and indicates that the cause is nonexistent or unknown.)
*/
public CertPathValidatorException(Throwable cause) {
super(cause);
this(null, cause);
}
/**
......@@ -117,7 +126,7 @@ public class CertPathValidatorException extends GeneralSecurityException {
* permitted, and indicates that the cause is nonexistent or unknown.)
*/
public CertPathValidatorException(String msg, Throwable cause) {
super(msg, cause);
this(msg, cause, null, -1);
}
/**
......@@ -139,6 +148,32 @@ public class CertPathValidatorException extends GeneralSecurityException {
*/
public CertPathValidatorException(String msg, Throwable cause,
CertPath certPath, int index) {
this(msg, cause, certPath, index, BasicReason.UNSPECIFIED);
}
/**
* Creates a <code>CertPathValidatorException</code> with the specified
* detail message, cause, certification path, index, and reason.
*
* @param msg the detail message (or <code>null</code> if none)
* @param cause the cause (or <code>null</code> if none)
* @param certPath the certification path that was in the process of
* being validated when the error was encountered
* @param index the index of the certificate in the certification path
* that caused the error (or -1 if not applicable). Note that
* the list of certificates in a <code>CertPath</code> is zero based.
* @param reason the reason the validation failed
* @throws IndexOutOfBoundsException if the index is out of range
* <code>(index < -1 || (certPath != null && index >=
* certPath.getCertificates().size())</code>
* @throws IllegalArgumentException if <code>certPath</code> is
* <code>null</code> and <code>index</code> is not -1
* @throws NullPointerException if <code>reason</code> is <code>null</code>
*
* @since 1.7
*/
public CertPathValidatorException(String msg, Throwable cause,
CertPath certPath, int index, Reason reason) {
super(msg, cause);
if (certPath == null && index != -1) {
throw new IllegalArgumentException();
......@@ -147,8 +182,12 @@ public class CertPathValidatorException extends GeneralSecurityException {
(certPath != null && index >= certPath.getCertificates().size())) {
throw new IndexOutOfBoundsException();
}
if (reason == null) {
throw new NullPointerException("reason can't be null");
}
this.certPath = certPath;
this.index = index;
this.reason = reason;
}
/**
......@@ -174,4 +213,79 @@ public class CertPathValidatorException extends GeneralSecurityException {
return this.index;
}
/**
* Returns the reason that the validation failed. The reason is
* associated with the index of the certificate returned by
* {@link getIndex}.
*
* @return the reason that the validation failed, or
* <code>BasicReason.UNSPECIFIED</code> if a reason has not been
* specified
*
* @since 1.7
*/
public Reason getReason() {
return this.reason;
}
private void readObject(ObjectInputStream stream)
throws ClassNotFoundException, IOException {
stream.defaultReadObject();
if (reason == null) {
reason = BasicReason.UNSPECIFIED;
}
if (certPath == null && index != -1) {
throw new InvalidObjectException("certpath is null and index != -1");
}
if (index < -1 ||
(certPath != null && index >= certPath.getCertificates().size())) {
throw new InvalidObjectException("index out of range");
}
}
/**
* The reason the validation algorithm failed.
*
* @since 1.7
*/
public static interface Reason extends java.io.Serializable { }
/**
* The BasicReason enumerates the potential reasons that a certification
* path of any type may be invalid.
*
* @since 1.7
*/
public static enum BasicReason implements Reason {
/**
* Unspecified reason.
*/
UNSPECIFIED,
/**
* The certificate is expired.
*/
EXPIRED,
/**
* The certificate is not yet valid.
*/
NOT_YET_VALID,
/**
* The certificate is revoked.
*/
REVOKED,
/**
* The revocation status of the certificate could not be determined.
*/
UNDETERMINED_REVOCATION_STATUS,
/**
* The signature is invalid.
*/
INVALID_SIGNATURE
}
}
/*
* 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 java.security.cert;
/**
* The <code>PKIXReason</code> enumerates the potential PKIX-specific reasons
* that an X.509 certification path may be invalid according to the PKIX
* (RFC 3280) standard. These reasons are in addition to those of the
* <code>CertPathValidatorException.BasicReason</code> enumeration.
*
* @since 1.7
*/
public enum PKIXReason implements CertPathValidatorException.Reason {
/**
* The certificate does not chain correctly.
*/
NAME_CHAINING,
/**
* The certificate's key usage is invalid.
*/
INVALID_KEY_USAGE,
/**
* The policy constraints have been violated.
*/
INVALID_POLICY,
/**
* No acceptable trust anchor found.
*/
NO_TRUST_ANCHOR,
/**
* The certificate contains one or more unrecognized critical
* extensions.
*/
UNRECOGNIZED_CRIT_EXT,
/**
* The certificate is not a CA certificate.
*/
NOT_CA_CERT,
/**
* The path length constraint has been violated.
*/
PATH_TOO_LONG,
/**
* The name constraints have been violated.
*/
INVALID_NAME
}
......@@ -118,6 +118,6 @@ class Logging implements LoggingMXBean {
}
public ObjectName getObjectName() {
return com.sun.jmx.mbeanserver.Util.newObjectName(LogManager.LOGGING_MXBEAN_NAME);
return ObjectName.valueOf(LogManager.LOGGING_MXBEAN_NAME);
}
}
/*
* Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1996-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
......@@ -73,11 +73,13 @@ package java.util.zip;
public
class Inflater {
private long strm;
private byte[] buf = new byte[0];
private byte[] buf = defaultBuf;
private int off, len;
private boolean finished;
private boolean needDict;
private static final byte[] defaultBuf = new byte[0];
static {
/* Zip library is loaded from System.initializeSystemClass */
initIDs();
......@@ -318,6 +320,7 @@ class Inflater {
public synchronized void reset() {
ensureOpen();
reset(strm);
buf = defaultBuf;
finished = false;
needDict = false;
off = len = 0;
......
/*
* Copyright 1995-2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1995-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
......@@ -278,7 +278,6 @@ class ZipFile implements ZipConstants {
int size = inflaters.size();
if (size > 0) {
Inflater inf = (Inflater)inflaters.remove(size - 1);
inf.reset();
return inf;
} else {
return new Inflater(true);
......@@ -291,6 +290,7 @@ class ZipFile implements ZipConstants {
*/
private void releaseInflater(Inflater inf) {
synchronized (inflaters) {
inf.reset();
inflaters.add(inf);
}
}
......
/*
* Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1996-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
......@@ -317,9 +317,6 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
if (current != null) {
closeEntry();
}
if (xentries.size() < 1) {
throw new ZipException("ZIP file must have at least one entry");
}
// write central directory
long off = written;
for (XEntry xentry : xentries)
......
......@@ -61,6 +61,6 @@ public class InstanceNotFoundException extends OperationsException {
* @since 1.7
*/
public InstanceNotFoundException(ObjectName name) {
this(name.toString());
this(String.valueOf(name));
}
}
......@@ -304,7 +304,7 @@ public class MBeanServerDelegate implements MBeanServerDelegateMBean,
* @since 1.6
*/
public static final ObjectName DELEGATE_NAME =
Util.newObjectName("JMImplementation:type=MBeanServerDelegate");
ObjectName.valueOf("JMImplementation:type=MBeanServerDelegate");
/* Return a timestamp that is monotonically increasing even if
System.currentTimeMillis() isn't (for example, if you call this
......
......@@ -413,7 +413,7 @@ public class ObjectName implements Comparable<ObjectName>, QueryExp {
}
private void copyToOtherDomain(String domain, ObjectName aname)
throws MalformedObjectNameException, NullPointerException {
throws MalformedObjectNameException {
// The domain cannot be null
if (domain == null)
......@@ -467,7 +467,7 @@ public class ObjectName implements Comparable<ObjectName>, QueryExp {
* is null.
*/
private void construct(String name)
throws MalformedObjectNameException, NullPointerException {
throws MalformedObjectNameException {
// The name cannot be null
if (name == null)
......@@ -729,7 +729,7 @@ public class ObjectName implements Comparable<ObjectName>, QueryExp {
* @exception NullPointerException One of the parameters is null.
*/
private void construct(String domain, Map<String,String> props)
throws MalformedObjectNameException, NullPointerException {
throws MalformedObjectNameException {
// The domain cannot be null
if (domain == null)
......@@ -1071,7 +1071,7 @@ public class ObjectName implements Comparable<ObjectName>, QueryExp {
* Check if the supplied key is a valid key.
*/
private static void checkKey(String key)
throws MalformedObjectNameException, NullPointerException {
throws MalformedObjectNameException {
if (key == null) throw new
NullPointerException("Invalid key (null)");
......@@ -1359,9 +1359,10 @@ public class ObjectName implements Comparable<ObjectName>, QueryExp {
* @exception NullPointerException The <code>name</code> parameter
* is null.
*
* @see #valueOf(String)
*/
public static ObjectName getInstance(String name)
throws MalformedObjectNameException, NullPointerException {
throws MalformedObjectNameException {
return new ObjectName(name);
}
......@@ -1386,10 +1387,11 @@ public class ObjectName implements Comparable<ObjectName>, QueryExp {
* follow the rules for quoting.
* @exception NullPointerException One of the parameters is null.
*
* @see #valueOf(String, String, String)
*/
public static ObjectName getInstance(String domain, String key,
String value)
throws MalformedObjectNameException, NullPointerException {
throws MalformedObjectNameException {
return new ObjectName(domain, key, value);
}
......@@ -1417,10 +1419,11 @@ public class ObjectName implements Comparable<ObjectName>, QueryExp {
* quoting.
* @exception NullPointerException One of the parameters is null.
*
* @see #valueOf(String, Hashtable)
*/
public static ObjectName getInstance(String domain,
Hashtable<String,String> table)
throws MalformedObjectNameException, NullPointerException {
throws MalformedObjectNameException {
return new ObjectName(domain, table);
}
......@@ -1453,11 +1456,120 @@ public class ObjectName implements Comparable<ObjectName>, QueryExp {
* @exception NullPointerException The <code>name</code> is null.
*
*/
public static ObjectName getInstance(ObjectName name)
throws NullPointerException {
public static ObjectName getInstance(ObjectName name) {
if (name.getClass().equals(ObjectName.class))
return name;
return Util.newObjectName(name.getSerializedNameString());
return valueOf(name.getSerializedNameString());
}
/**
* <p>Return an instance of ObjectName that can be used anywhere
* an object obtained with {@link #ObjectName(String) new
* ObjectName(name)} can be used. The returned object may be of
* a subclass of ObjectName. Calling this method twice with the
* same parameters may return the same object or two equal but
* not identical objects.</p>
*
* <p>This method is equivalent to {@link #getInstance(String)} except that
* it does not throw any checked exceptions.</p>
*
* @param name A string representation of the object name.
*
* @return an ObjectName corresponding to the given String.
*
* @exception IllegalArgumentException The string passed as a
* parameter does not have the right format. The {@linkplain
* Throwable#getCause() cause} of this exception will be a
* {@link MalformedObjectNameException}.
* @exception NullPointerException The <code>name</code> parameter
* is null.
*
* @since 1.7
*/
public static ObjectName valueOf(String name) {
try {
return getInstance(name);
} catch (MalformedObjectNameException e) {
throw new IllegalArgumentException(e.getMessage(), e);
// Just plain IllegalArgumentException(e) produces an exception
// message "javax.management.MalformedObjectNameException: ..."
// which is distracting.
}
}
/**
* <p>Return an instance of ObjectName that can be used anywhere
* an object obtained with {@link #ObjectName(String, String,
* String) new ObjectName(domain, key, value)} can be used. The
* returned object may be of a subclass of ObjectName. Calling
* this method twice with the same parameters may return the same
* object or two equal but not identical objects.</p>
*
* <p>This method is equivalent to {@link #getInstance(String, String,
* String)} except that it does not throw any checked exceptions.</p>
*
* @param domain The domain part of the object name.
* @param key The attribute in the key property of the object name.
* @param value The value in the key property of the object name.
*
* @return an ObjectName corresponding to the given domain,
* key, and value.
*
* @exception IllegalArgumentException The
* <code>domain</code>, <code>key</code>, or <code>value</code>
* contains an illegal character, or <code>value</code> does not
* follow the rules for quoting. The {@linkplain
* Throwable#getCause() cause} of this exception will be a
* {@link MalformedObjectNameException}.
* @exception NullPointerException One of the parameters is null.
*
* @since 1.7
*/
public static ObjectName valueOf(String domain, String key, String value) {
try {
return getInstance(domain, key, value);
} catch (MalformedObjectNameException e) {
throw new IllegalArgumentException(e.getMessage(), e);
}
}
/**
* <p>Return an instance of ObjectName that can be used anywhere
* an object obtained with {@link #ObjectName(String, Hashtable)
* new ObjectName(domain, table)} can be used. The returned
* object may be of a subclass of ObjectName. Calling this method
* twice with the same parameters may return the same object or
* two equal but not identical objects.</p>
*
* <p>This method is equivalent to {@link #getInstance(String, Hashtable)}
* except that it does not throw any checked exceptions.</p>
*
* @param domain The domain part of the object name.
* @param table A hash table containing one or more key
* properties. The key of each entry in the table is the key of a
* key property in the object name. The associated value in the
* table is the associated value in the object name.
*
* @return an ObjectName corresponding to the given domain and
* key mappings.
*
* @exception IllegalArgumentException The <code>domain</code>
* contains an illegal character, or one of the keys or values in
* <code>table</code> contains an illegal character, or one of the
* values in <code>table</code> does not follow the rules for
* quoting. The {@linkplain Throwable#getCause() cause} of this exception
* will be a {@link MalformedObjectNameException}.
* @exception NullPointerException One of the parameters is null.
*
* @since 1.7
*/
public static ObjectName valueOf(String domain,
Hashtable<String,String> table) {
try {
return new ObjectName(domain, table);
} catch (MalformedObjectNameException e) {
throw new IllegalArgumentException(e.getMessage(), e);
}
}
/**
......@@ -1477,7 +1589,7 @@ public class ObjectName implements Comparable<ObjectName>, QueryExp {
* @since 1.7
**/
public final ObjectName withDomain(String newDomain)
throws NullPointerException, MalformedObjectNameException {
throws MalformedObjectNameException {
return new ObjectName(newDomain, this);
}
......@@ -1490,9 +1602,11 @@ public class ObjectName implements Comparable<ObjectName>, QueryExp {
* parameter does not have the right format.
* @exception NullPointerException The <code>name</code> parameter
* is null.
*
* @see #valueOf(String)
*/
public ObjectName(String name)
throws MalformedObjectNameException, NullPointerException {
throws MalformedObjectNameException {
construct(name);
}
......@@ -1508,9 +1622,11 @@ public class ObjectName implements Comparable<ObjectName>, QueryExp {
* contains an illegal character, or <code>value</code> does not
* follow the rules for quoting.
* @exception NullPointerException One of the parameters is null.
*
* @see #valueOf(String, String, String)
*/
public ObjectName(String domain, String key, String value)
throws MalformedObjectNameException, NullPointerException {
throws MalformedObjectNameException {
// If key or value are null a NullPointerException
// will be thrown by the put method in Hashtable.
//
......@@ -1533,9 +1649,11 @@ public class ObjectName implements Comparable<ObjectName>, QueryExp {
* values in <code>table</code> does not follow the rules for
* quoting.
* @exception NullPointerException One of the parameters is null.
*
* @see #valueOf(String, Hashtable)
*/
public ObjectName(String domain, Hashtable<String,String> table)
throws MalformedObjectNameException, NullPointerException {
throws MalformedObjectNameException {
construct(domain, table);
/* The exception for when a key or value in the table is not a
String is now ClassCastException rather than
......@@ -1629,8 +1747,7 @@ public class ObjectName implements Comparable<ObjectName>, QueryExp {
*
* @since 1.6
*/
public boolean isPropertyValuePattern(String property)
throws NullPointerException, IllegalArgumentException {
public boolean isPropertyValuePattern(String property) {
if (property == null)
throw new NullPointerException("key property can't be null");
for (int i = 0; i < _ca_array.length; i++) {
......@@ -1691,7 +1808,7 @@ public class ObjectName implements Comparable<ObjectName>, QueryExp {
*
* @exception NullPointerException If <code>property</code> is null.
*/
public String getKeyProperty(String property) throws NullPointerException {
public String getKeyProperty(String property) {
return _getKeyPropertyList().get(property);
}
......@@ -1950,8 +2067,7 @@ public class ObjectName implements Comparable<ObjectName>, QueryExp {
* @exception NullPointerException if <code>s</code> is null.
*
*/
public static String quote(String s)
throws NullPointerException {
public static String quote(String s) {
final StringBuilder buf = new StringBuilder("\"");
final int len = s.length();
for (int i = 0; i < len; i++) {
......@@ -1995,8 +2111,7 @@ public class ObjectName implements Comparable<ObjectName>, QueryExp {
* @exception NullPointerException if <code>q</code> is null.
*
*/
public static String unquote(String q)
throws IllegalArgumentException, NullPointerException {
public static String unquote(String q) {
final StringBuilder buf = new StringBuilder();
final int len = q.length();
if (len < 2 || q.charAt(0) != '"' || q.charAt(len - 1) != '"')
......@@ -2041,7 +2156,7 @@ public class ObjectName implements Comparable<ObjectName>, QueryExp {
*
* @since 1.6
*/
public static final ObjectName WILDCARD = Util.newObjectName("*:*");
public static final ObjectName WILDCARD = valueOf("*:*");
// Category : Utilities <===================================
......@@ -2064,7 +2179,7 @@ public class ObjectName implements Comparable<ObjectName>, QueryExp {
* @exception NullPointerException if <code>name</code> is null.
*
*/
public boolean apply(ObjectName name) throws NullPointerException {
public boolean apply(ObjectName name) {
if (name == null) throw new NullPointerException();
......
......@@ -170,7 +170,7 @@ public class QueryNotificationFilter implements NotificationFilter {
private static final long serialVersionUID = -8408613922660635231L;
private static final ObjectName DEFAULT_NAME =
Util.newObjectName(":type=Notification");
ObjectName.valueOf(":type=Notification");
private static final QueryExp trueQuery;
static {
ValueExp zero = Query.value(0);
......
......@@ -264,11 +264,12 @@ public class EventClient implements EventConsumer, NotificationManager {
new PerThreadGroupPool.Create<ScheduledThreadPoolExecutor>() {
public ScheduledThreadPoolExecutor createThreadPool(ThreadGroup group) {
ThreadFactory daemonThreadFactory = new DaemonThreadFactory(
"EventClient lease renewer %d");
"JMX EventClient lease renewer %d");
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(
20, daemonThreadFactory);
exec.setKeepAliveTime(3, TimeUnit.SECONDS);
exec.setKeepAliveTime(1, TimeUnit.SECONDS);
exec.allowCoreThreadTimeOut(true);
exec.setRemoveOnCancelPolicy(true);
return exec;
}
};
......
......@@ -96,7 +96,7 @@ public interface EventClientDelegateMBean {
* <code>{@value #OBJECT_NAME_STRING}</code>.
*/
public final static ObjectName OBJECT_NAME =
Util.newObjectName(OBJECT_NAME_STRING);
ObjectName.valueOf(OBJECT_NAME_STRING);
/**
* A unique listener identifier specified for an EventClient.
......
......@@ -149,10 +149,10 @@ public class EventSubscriber implements EventConsumer {
if (listener == null)
throw new IllegalArgumentException("Null listener");
final ListenerInfo li = new ListenerInfo(listener, filter, handback);
List<ListenerInfo> list;
final MyListenerInfo li = new MyListenerInfo(listener, filter, handback);
List<MyListenerInfo> list;
Map<ObjectName, List<ListenerInfo>> map;
Map<ObjectName, List<MyListenerInfo>> map;
Set<ObjectName> names;
if (name.isPattern()) {
map = patternSubscriptionMap;
......@@ -165,7 +165,7 @@ public class EventSubscriber implements EventConsumer {
synchronized (map) {
list = map.get(name);
if (list == null) {
list = new ArrayList<ListenerInfo>();
list = new ArrayList<MyListenerInfo>();
map.put(name, list);
}
list.add(li);
......@@ -186,7 +186,6 @@ public class EventSubscriber implements EventConsumer {
public void unsubscribe(ObjectName name,
NotificationListener listener)
throws ListenerNotFoundException, IOException {
if (logger.traceOn())
logger.trace("unsubscribe", "" + name);
......@@ -196,7 +195,7 @@ public class EventSubscriber implements EventConsumer {
if (listener == null)
throw new ListenerNotFoundException();
Map<ObjectName, List<ListenerInfo>> map;
Map<ObjectName, List<MyListenerInfo>> map;
Set<ObjectName> names;
if (name.isPattern()) {
......@@ -207,22 +206,39 @@ public class EventSubscriber implements EventConsumer {
names = Collections.singleton(name);
}
final ListenerInfo li = new ListenerInfo(listener, null, null);
List<ListenerInfo> list;
List<MyListenerInfo> toRemove = new ArrayList<MyListenerInfo>();
synchronized (map) {
list = map.get(name);
if (list == null || !list.remove(li))
List<MyListenerInfo> list = map.get(name);
if (list == null) {
throw new ListenerNotFoundException();
}
for (MyListenerInfo info : list) {
if (info.listener == listener) {
toRemove.add(info);
}
}
if (toRemove.isEmpty()) {
throw new ListenerNotFoundException();
}
for (MyListenerInfo info : toRemove) {
list.remove(info);
}
if (list.isEmpty())
map.remove(name);
}
for (ObjectName mbeanName : names) {
try {
mbeanServer.removeNotificationListener(mbeanName, li.listener);
} catch (Exception e) {
logger.fine("unsubscribe", "removeNotificationListener", e);
for (MyListenerInfo i : toRemove) {
try {
mbeanServer.removeNotificationListener(mbeanName,
i.listener, i.filter, i.handback);
} catch (Exception e) {
logger.fine("unsubscribe", "removeNotificationListener", e);
}
}
}
}
......@@ -256,12 +272,12 @@ public class EventSubscriber implements EventConsumer {
return;
}
final List<ListenerInfo> listeners = new ArrayList<ListenerInfo>();
final List<MyListenerInfo> listeners = new ArrayList<MyListenerInfo>();
// If there are subscribers for the exact name that has just arrived
// then add their listeners to the list.
synchronized (exactSubscriptionMap) {
List<ListenerInfo> exactListeners = exactSubscriptionMap.get(name);
List<MyListenerInfo> exactListeners = exactSubscriptionMap.get(name);
if (exactListeners != null)
listeners.addAll(exactListeners);
}
......@@ -277,7 +293,7 @@ public class EventSubscriber implements EventConsumer {
}
// Add all the listeners just found to the new MBean.
for (ListenerInfo li : listeners) {
for (MyListenerInfo li : listeners) {
try {
mbeanServer.addNotificationListener(
name,
......@@ -292,12 +308,12 @@ public class EventSubscriber implements EventConsumer {
}
};
private static class ListenerInfo {
private static class MyListenerInfo {
public final NotificationListener listener;
public final NotificationFilter filter;
public final Object handback;
public ListenerInfo(NotificationListener listener,
public MyListenerInfo(NotificationListener listener,
NotificationFilter filter,
Object handback) {
......@@ -308,26 +324,6 @@ public class EventSubscriber implements EventConsumer {
this.filter = filter;
this.handback = handback;
}
/* Two ListenerInfo instances are equal if they have the same
* NotificationListener. This means that we can use List.remove
* to implement the two-argument removeNotificationListener.
*/
@Override
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof ListenerInfo))
return false;
return listener.equals(((ListenerInfo)o).listener);
}
@Override
public int hashCode() {
return listener.hashCode();
}
}
// ---------------------------------
......@@ -338,10 +334,10 @@ public class EventSubscriber implements EventConsumer {
// ---------------------------------
private final MBeanServer mbeanServer;
private final Map<ObjectName, List<ListenerInfo>> exactSubscriptionMap =
new HashMap<ObjectName, List<ListenerInfo>>();
private final Map<ObjectName, List<ListenerInfo>> patternSubscriptionMap =
new HashMap<ObjectName, List<ListenerInfo>>();
private final Map<ObjectName, List<MyListenerInfo>> exactSubscriptionMap =
new HashMap<ObjectName, List<MyListenerInfo>>();
private final Map<ObjectName, List<MyListenerInfo>> patternSubscriptionMap =
new HashMap<ObjectName, List<MyListenerInfo>>();
......
......@@ -31,10 +31,8 @@ import com.sun.jmx.remote.util.ClassLogger;
import java.io.IOException;
import java.io.NotSerializableException;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import javax.management.MBeanException;
......@@ -215,50 +213,47 @@ public class FetchingEventRelay implements EventRelay {
this.maxNotifs = maxNotifs;
if (executor == null) {
executor = Executors.newSingleThreadScheduledExecutor(
ScheduledThreadPoolExecutor stpe = new ScheduledThreadPoolExecutor(1,
daemonThreadFactory);
}
stpe.setKeepAliveTime(1, TimeUnit.SECONDS);
stpe.allowCoreThreadTimeOut(true);
executor = stpe;
this.defaultExecutor = stpe;
} else
this.defaultExecutor = null;
this.executor = executor;
if (executor instanceof ScheduledExecutorService)
leaseScheduler = (ScheduledExecutorService) executor;
else {
leaseScheduler = Executors.newSingleThreadScheduledExecutor(
daemonThreadFactory);
}
startSequenceNumber = 0;
fetchingJob = new MyJob();
}
public void setEventReceiver(EventReceiver eventReceiver) {
public synchronized void setEventReceiver(EventReceiver eventReceiver) {
if (logger.traceOn()) {
logger.trace("setEventReceiver", ""+eventReceiver);
}
EventReceiver old = this.eventReceiver;
synchronized(fetchingJob) {
this.eventReceiver = eventReceiver;
if (old == null && eventReceiver != null)
fetchingJob.resume();
}
this.eventReceiver = eventReceiver;
if (old == null && eventReceiver != null)
fetchingJob.resume();
}
public String getClientId() {
return clientId;
}
public void stop() {
public synchronized void stop() {
if (logger.traceOn()) {
logger.trace("stop", "");
}
synchronized(fetchingJob) {
if (stopped) {
return;
}
stopped = true;
clientId = null;
if (stopped) {
return;
}
stopped = true;
clientId = null;
if (defaultExecutor != null)
defaultExecutor.shutdown();
}
private class MyJob extends RepeatedSingletonJob {
......@@ -372,10 +367,9 @@ public class FetchingEventRelay implements EventRelay {
private final EventClientDelegateMBean delegate;
private String clientId;
private boolean stopped = false;
private volatile ScheduledFuture<?> leaseRenewalFuture;
private final Executor executor;
private final ScheduledExecutorService leaseScheduler;
private final ExecutorService defaultExecutor;
private final MyJob fetchingJob;
private final long timeout;
......@@ -385,5 +379,5 @@ public class FetchingEventRelay implements EventRelay {
new ClassLogger("javax.management.event",
"FetchingEventRelay");
private static final ThreadFactory daemonThreadFactory =
new DaemonThreadFactory("FetchingEventRelay-executor");
new DaemonThreadFactory("JMX FetchingEventRelay executor %d");
}
......@@ -185,7 +185,7 @@ public class RMIPushEventForwarder implements EventForwarder {
private static final ExecutorService executor =
Executors.newCachedThreadPool(
new DaemonThreadFactory("RMIEventForwarder Executor"));
new DaemonThreadFactory("JMX RMIEventForwarder Executor"));
private final SendingJob sendingJob = new SendingJob();
private final BlockingQueue<TargetedNotification> buffer;
......
......@@ -308,17 +308,17 @@ public class JMXDomain extends JMXNamespace {
* It is however only available for subclasses in this package.
**/
@Override
ObjectName validateHandlerName(ObjectName supliedName) {
if (supliedName == null)
ObjectName validateHandlerName(ObjectName suppliedName) {
if (suppliedName == null)
throw new IllegalArgumentException("Must supply a valid name");
final String dirName = JMXNamespaces.
normalizeNamespaceName(supliedName.getDomain());
normalizeNamespaceName(suppliedName.getDomain());
final ObjectName handlerName = getDomainObjectName(dirName);
if (!supliedName.equals(handlerName))
if (!suppliedName.equals(handlerName))
throw new IllegalArgumentException("invalid name space name: "+
supliedName);
suppliedName);
return supliedName;
return suppliedName;
}
/**
......
......@@ -482,8 +482,8 @@ public class JMXNamespace
/**
* This method is part of the {@link MBeanRegistration} interface.
* The {@link JMXNamespace} class uses the {@link MBeanRegistration}
* interface in order to get a handle to the MBean server in which it is
* registered. It also check the validity of its own ObjectName.
* 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.
......@@ -502,11 +502,14 @@ public class JMXNamespace
*/
public ObjectName preRegister(MBeanServer server, ObjectName name)
throws Exception {
if (objectName != null && ! objectName.equals(name))
throw new IllegalStateException(
// 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;
objectName = validateHandlerName(name);
mbeanServer = server;
}
return name;
}
......@@ -517,23 +520,23 @@ public class JMXNamespace
* reuse JMXNamespace in order to implement sessions...
* It is however only available for subclasses in this package.
**/
ObjectName validateHandlerName(ObjectName supliedName) {
if (supliedName == null)
ObjectName validateHandlerName(ObjectName suppliedName) {
if (suppliedName == null)
throw new IllegalArgumentException("Must supply a valid name");
final String dirName = JMXNamespaces.
normalizeNamespaceName(supliedName.getDomain());
normalizeNamespaceName(suppliedName.getDomain());
final ObjectName handlerName =
JMXNamespaces.getNamespaceObjectName(dirName);
if (!supliedName.equals(handlerName))
if (!suppliedName.equals(handlerName))
throw new IllegalArgumentException("invalid name space name: "+
supliedName);
return supliedName;
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 handle to the MBean server in which it is
* 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
......@@ -549,7 +552,7 @@ public class JMXNamespace
/**
* This method is part of the {@link MBeanRegistration} interface.
* The {@link JMXNamespace} class uses the {@link MBeanRegistration}
* interface in order to get a handle to the MBean server in which it is
* 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
......@@ -573,8 +576,11 @@ public class JMXNamespace
* @see MBeanRegistration#postDeregister MBeanRegistration
*/
public void postDeregister() {
mbeanServer = null;
objectName = null;
// need to synchronize to protect against multiple registration.
synchronized(this) {
mbeanServer = null;
objectName = null;
}
}
......
......@@ -266,11 +266,15 @@ public class JMXNamespaces {
ObjectNameRouter.normalizeNamespacePath(namespace,false,
true,false);
try {
// We could use Util.newObjectName here - but throwing an
// IllegalArgumentException that contains just the supplied
// namespace instead of the whole ObjectName seems preferable.
return ObjectName.getInstance(sourcePath+
NAMESPACE_SEPARATOR+":"+
JMXNamespace.TYPE_ASSIGNMENT);
} catch (MalformedObjectNameException x) {
throw new IllegalArgumentException(namespace,x);
throw new IllegalArgumentException("Invalid namespace: " +
namespace,x);
}
}
......
......@@ -28,7 +28,6 @@ package javax.management.namespace;
import com.sun.jmx.mbeanserver.Util;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.security.AccessController;
import java.util.Set;
import javax.management.Attribute;
......
......@@ -193,14 +193,6 @@ import javax.management.loading.ClassLoaderRepository;
* }
*
* <a name="PropsMBS"></a>public class PropsMBS extends MBeanServerSupport {
* private static ObjectName newObjectName(String name) {
* try {
* return new ObjectName(name);
* } catch (MalformedObjectNameException e) {
* throw new AssertionError(e);
* }
* }
*
* public static class PropertyImpl implements PropertyMBean {
* private final String name;
*
......@@ -219,7 +211,7 @@ import javax.management.loading.ClassLoaderRepository;
* throws InstanceNotFoundException {
*
* // Check that the name is a legal one for a Property MBean
* ObjectName namePattern = newObjectName(
* ObjectName namePattern = ObjectName.valueOf(
* "com.example:type=Property,name=\"*\"");
* if (!namePattern.apply(name))
* throw new InstanceNotFoundException(name);
......@@ -239,7 +231,7 @@ import javax.management.loading.ClassLoaderRepository;
* {@code Set<ObjectName> names = new TreeSet<ObjectName>();}
* Properties props = System.getProperties();
* for (String propName : props.stringPropertyNames()) {
* ObjectName objectName = newObjectName(
* ObjectName objectName = ObjectName.valueOf(
* "com.example:type=Property,name=" +
* ObjectName.quote(propName));
* names.add(objectName);
......@@ -278,7 +270,7 @@ import javax.management.loading.ClassLoaderRepository;
* }
*
* public void propertyChanged(String name, String newValue) {
* ObjectName objectName = newObjectName(
* ObjectName objectName = ObjectName.valueOf(
* "com.example:type=Property,name=" + ObjectName.quote(name));
* Notification n = new Notification(
* "com.example.property.changed", objectName, 0L,
......
......@@ -420,7 +420,7 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable
new PerThreadGroupPool.Create<ThreadPoolExecutor>() {
public ThreadPoolExecutor createThreadPool(ThreadGroup group) {
ThreadFactory daemonThreadFactory = new DaemonThreadFactory(
"RMIConnector listener dispatch %d");
"JMX RMIConnector listener dispatch %d");
ThreadPoolExecutor exec = new ThreadPoolExecutor(
1, 10, 1, TimeUnit.SECONDS,
new LinkedBlockingDeque<Runnable>(),
......
......@@ -71,6 +71,6 @@ class ClassLoadingImpl implements ClassLoadingMXBean {
native static void setVerboseClass(boolean value);
public ObjectName getObjectName() {
return Util.newObjectName(ManagementFactory.CLASS_LOADING_MXBEAN_NAME);
return ObjectName.valueOf(ManagementFactory.CLASS_LOADING_MXBEAN_NAME);
}
}
......@@ -70,7 +70,7 @@ class CompilationImpl implements CompilationMXBean {
}
public ObjectName getObjectName() {
return Util.newObjectName(ManagementFactory.COMPILATION_MXBEAN_NAME);
return ObjectName.valueOf(ManagementFactory.COMPILATION_MXBEAN_NAME);
}
......
......@@ -117,6 +117,6 @@ public class HotSpotDiagnostic implements HotSpotDiagnosticMXBean {
}
public ObjectName getObjectName() {
return Util.newObjectName("com.sun.management:type=HotSpotDiagnostic");
return ObjectName.valueOf("com.sun.management:type=HotSpotDiagnostic");
}
}
......@@ -41,7 +41,7 @@ public class HotspotInternal
private final static String HOTSPOT_INTERNAL_MBEAN_NAME =
"sun.management:type=HotspotInternal";
private static ObjectName objName = Util.newObjectName(HOTSPOT_INTERNAL_MBEAN_NAME);
private static ObjectName objName = ObjectName.valueOf(HOTSPOT_INTERNAL_MBEAN_NAME);
private MBeanServer server = null;
/**
......
......@@ -220,7 +220,7 @@ public class ManagementFactoryHelper {
*/
private static void addMBean(MBeanServer mbs, Object mbean, String mbeanName) {
try {
final ObjectName objName = Util.newObjectName(mbeanName);
final ObjectName objName = ObjectName.valueOf(mbeanName);
// inner class requires these fields to be final
final MBeanServer mbs0 = mbs;
......@@ -280,7 +280,7 @@ public class ManagementFactoryHelper {
private static void unregisterMBean(MBeanServer mbs, String mbeanName) {
try {
final ObjectName objName = Util.newObjectName(mbeanName);
final ObjectName objName = ObjectName.valueOf(mbeanName);
// inner class requires these fields to be final
final MBeanServer mbs0 = mbs;
......
......@@ -177,7 +177,7 @@ class MemoryImpl extends NotificationEmitterSupport
}
public ObjectName getObjectName() {
return Util.newObjectName(ManagementFactory.MEMORY_MXBEAN_NAME);
return ObjectName.valueOf(ManagementFactory.MEMORY_MXBEAN_NAME);
}
}
......@@ -74,7 +74,7 @@ public class OperatingSystemImpl implements OperatingSystemMXBean {
}
}
public ObjectName getObjectName() {
return Util.newObjectName(ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME);
return ObjectName.valueOf(ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME);
}
}
......
......@@ -149,7 +149,7 @@ class RuntimeImpl implements RuntimeMXBean {
}
public ObjectName getObjectName() {
return Util.newObjectName(ManagementFactory.RUNTIME_MXBEAN_NAME);
return ObjectName.valueOf(ManagementFactory.RUNTIME_MXBEAN_NAME);
}
}
......@@ -415,7 +415,7 @@ class ThreadImpl implements ThreadMXBean {
private static native void resetContentionTimes0(long tid);
public ObjectName getObjectName() {
return Util.newObjectName(ManagementFactory.THREAD_MXBEAN_NAME);
return ObjectName.valueOf(ManagementFactory.THREAD_MXBEAN_NAME);
}
}
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册