Merge
authortbell
Mon Sep 22 22:37:31 2008 -0700 (17 months ago)
changeset 592b54ba7058851
parent 565134fd1a656ea
parent 5914a62773bf60e
child 593ed8f850f9f94
Merge
--- a/src/share/classes/com/sun/jmx/event/LeaseManager.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/com/sun/jmx/event/LeaseManager.java Mon Sep 22 22:37:31 2008 -0700
@@ -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");
--- a/src/share/classes/com/sun/jmx/event/RepeatedSingletonJob.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/com/sun/jmx/event/RepeatedSingletonJob.java Mon Sep 22 22:37:31 2008 -0700
@@ -95,7 +95,9 @@ public abstract class RepeatedSingletonJ
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);
--- a/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java Mon Sep 22 22:37:31 2008 -0700
@@ -613,8 +613,7 @@ public class DefaultMBeanServerIntercept
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 DefaultMBeanServerIntercept
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 DefaultMBeanServerIntercept
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 DefaultMBeanServerIntercept
private void removeJMXNamespace(JMXNamespace namespace,
final ObjectName logicalName,
final Queue<Runnable> postQueue) {
- dispatcher.removeNamespace(logicalName, namespace, postQueue);
+ dispatcher.removeInterceptorFor(logicalName, namespace, postQueue);
}
/**
--- a/src/share/classes/com/sun/jmx/interceptor/DispatchInterceptor.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/com/sun/jmx/interceptor/DispatchInterceptor.java Mon Sep 22 22:37:31 2008 -0700
@@ -194,7 +194,7 @@ public abstract class DispatchIntercepto
// 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 DispatchIntercepto
// 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 DispatchIntercepto
// 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 DispatchIntercepto
}
// 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 DispatchIntercepto
}
// 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 DispatchIntercepto
}
// 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 DispatchIntercepto
}
// 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 DispatchIntercepto
}
// 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);
- }
-
- // From MBeanServer
- public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
- final QueryInterceptor mbs =
+ if (queryInvoker == null) return Collections.emptySet();
+ else return queryInvoker.queryMBeans(name,query);
+ }
+
+ // From MBeanServer
+ 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);
- }
-
- // From MBeanServer
- public boolean isRegistered(ObjectName name) {
+ if (queryInvoker == null) return Collections.emptySet();
+ else return queryInvoker.queryNames(name,query);
+ }
+
+ // From MBeanServer
+ 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 DispatchIntercepto
}
// 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 DispatchIntercepto
}
// 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 DispatchIntercepto
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);
- }
-
- // From MBeanServer
- public void removeNotificationListener(ObjectName name,
+ getInterceptorForInstance(name).
+ removeNotificationListener(name,listener);
+ }
+
+ // From MBeanServer
+ 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);
- }
-
- // From MBeanServer
- public void removeNotificationListener(ObjectName name,
+ getInterceptorForInstance(name).
+ removeNotificationListener(name,listener);
+ }
+
+ // From MBeanServer
+ 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 DispatchIntercepto
// 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);
- }
-
- // From MBeanServer
- public ClassLoader getClassLoader(ObjectName loaderName)
+ return getInterceptorForInstance(mbeanName).
+ getClassLoaderFor(mbeanName);
+ }
+
+ // From MBeanServer
+ public final ClassLoader getClassLoader(ObjectName loaderName)
throws InstanceNotFoundException {
- return getInterceptorForInstance(loaderName).getClassLoader(loaderName);
+ return getInterceptorForInstance(loaderName).
+ getClassLoader(loaderName);
}
}
--- a/src/share/classes/com/sun/jmx/interceptor/DomainDispatchInterceptor.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/com/sun/jmx/interceptor/DomainDispatchInterceptor.java Mon Sep 22 22:37:31 2008 -0700
@@ -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;
- }
- final DomainInterceptor ns = getInterceptor(localDomain);
+ return nextInterceptor;
+ }
+
+ 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();
- }
- return Integer.valueOf(count);
+ count += mbs.getMBeanCount();
+ }
+ return count;
}
}
--- a/src/share/classes/com/sun/jmx/interceptor/NamespaceDispatchInterceptor.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/com/sun/jmx/interceptor/NamespaceDispatchInterceptor.java Mon Sep 22 22:37:31 2008 -0700
@@ -61,7 +61,7 @@ public class NamespaceDispatchIntercepto
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 NamespaceDispatchIntercepto
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 NamespaceDispatchIntercepto
* 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;
- }
-
- if (end == -1) return "";
-
+ while (domain.startsWith(NAMESPACE_SEPARATOR,first))
+ first += NAMESPACE_SEPARATOR_LENGTH;
+
+ // 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 NamespaceDispatchIntercepto
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 NamespaceDispatchIntercepto
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 NamespaceDispatchIntercepto
@Override
final DomainDispatchInterceptor getNextInterceptor() {
- return localNamespace;
+ return nextInterceptor;
}
/**
@@ -211,25 +211,25 @@ public class NamespaceDispatchIntercepto
*/
@Override
public String[] getDomains() {
- return localNamespace.getDomains();
- }
-
- @Override
- public void addNamespace(ObjectName name, JMXNamespace handler,
+ return nextInterceptor.getDomains();
+ }
+
+ @Override
+ 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);
- }
-
- @Override
- public void removeNamespace(ObjectName name, JMXNamespace handler,
+ else super.addInterceptorFor(name,handler,postRegisterQueue);
+ }
+
+ @Override
+ 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);
}
--- a/src/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java Mon Sep 22 22:37:31 2008 -0700
@@ -1172,10 +1172,10 @@ public class DefaultMXBeanMappingFactory
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
// 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
}
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;
--- a/src/share/classes/com/sun/jmx/mbeanserver/MBeanIntrospector.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/com/sun/jmx/mbeanserver/MBeanIntrospector.java Mon Sep 22 22:37:31 2008 -0700
@@ -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";
--- a/src/share/classes/com/sun/jmx/mbeanserver/Repository.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/com/sun/jmx/mbeanserver/Repository.java Mon Sep 22 22:37:31 2008 -0700
@@ -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)
--- a/src/share/classes/com/sun/jmx/mbeanserver/Util.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/com/sun/jmx/mbeanserver/Util.java Mon Sep 22 22:37:31 2008 -0700
@@ -57,7 +57,8 @@ public class Util {
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() {
@@ -107,14 +108,6 @@ public class Util {
static <E> List<E> newList(Collection<E> c) {
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
@@ -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());
}
}
--- a/src/share/classes/com/sun/jmx/namespace/DomainInterceptor.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/com/sun/jmx/namespace/DomainInterceptor.java Mon Sep 22 22:37:31 2008 -0700
@@ -85,7 +85,7 @@ public class DomainInterceptor extends H
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 H
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 H
super(handler);
this.domainName = domainName;
this.serverName = serverName;
+ ALL = ObjectName.valueOf(domainName+":*");
}
@Override
@@ -118,27 +119,27 @@ public class DomainInterceptor extends H
", 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);
- }
- };
- }
-
- getNamespace().
+ public void handleNotification(Notification notification,
+ Object handback) {
+ if (filter.isNotificationEnabled(notification))
+ delegate.sendNotification(notification);
+ }
+ };
+ }
+ }
+
+ 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 H
if (l == null) return;
mbsListener = null;
}
- getNamespace().removeMBeanServerNotificationListener(l);
- }
-
- public void addPostRegisterTask(Queue<Runnable> queue,
+ getHandlerInterceptorMBean().removeMBeanServerNotificationListener(l);
+ }
+
+ 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 H
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 H
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 H
return targetName;
}
+ // No name conversion for JMXDomains...
@Override
protected ObjectName toTarget(ObjectName sourceName) {
return sourceName;
@@ -255,16 +259,16 @@ public class DomainInterceptor extends H
if (LOG.isLoggable(Level.FINE))
LOG.fine("Unexpected exception raised in queryNames: "+x);
LOG.log(Level.FINEST,"Unexpected exception raised in queryNames",x);
- }
- // We reach here only when an exception was raised.
- //
- final Set<ObjectName> empty = Collections.emptySet();
- return empty;
- }
-
+ return Collections.emptySet();
+ }
+ }
+
+ // 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 H
if (LOG.isLoggable(Level.FINE))
LOG.fine("Unexpected exception raised in queryNames: "+x);
LOG.log(Level.FINEST,"Unexpected exception raised in queryNames",x);
- }
- // We reach here only when an exception was raised.
- //
- final Set<ObjectInstance> empty = Collections.emptySet();
- return empty;
+ return Collections.emptySet();
+ }
}
@Override
@@ -306,7 +307,7 @@ public class DomainInterceptor extends H
// in the domain.
@Override
public Integer getMBeanCount() {
- return getNamespace().getMBeanCount();
+ return getHandlerInterceptorMBean().getMBeanCount();
}
private boolean checkOn() {
@@ -320,8 +321,8 @@ public class DomainInterceptor extends H
@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 H
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 H
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 H
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++;
--- a/src/share/classes/com/sun/jmx/namespace/HandlerInterceptor.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/com/sun/jmx/namespace/HandlerInterceptor.java Mon Sep 22 22:37:31 2008 -0700
@@ -63,8 +63,8 @@ import javax.management.namespace.JMXNam
/**
* This interceptor wraps a JMXNamespace, and performs
* {@code ObjectName} rewriting. {@code HandlerInterceptor} are
- * usually created and managed by a {@link NamespaceDispatcher} or
- * {@link DomainDispatcher}.
+ * created and managed by a {@link NamespaceDispatchInterceptor} or a
+ * {@link DomainDispatchInterceptor}.
* <p><b>
* This API is a Sun internal API and is subject to changes without notice.
* </b></p>
@@ -90,6 +90,12 @@ public abstract class HandlerInterceptor
this.handler = handler;
}
+ //
+ // The {@code source} connection is a connection to the MBeanServer
+ // that contains the actual MBeans.
+ // In the case of cascading, that would be a connection to the sub
+ // agent. Practically, this is JMXNamespace.getSourceServer();
+ //
@Override
protected MBeanServer source() {
return handler.getSourceServer();
@@ -105,7 +111,9 @@ public abstract class HandlerInterceptor
return source();
}
- T getNamespace() {
+ // The namespace or domain handler - this either a JMXNamespace or a
+ // a JMXDomain
+ T getHandlerInterceptorMBean() {
return handler;
}
@@ -122,12 +130,16 @@ public abstract class HandlerInterceptor
Util.newRuntimeIOException(x));
}
- // From MBeanServer: catch & handles IOException
+ // From MBeanServerConnection: catch & handles IOException
@Override
public AttributeList getAttributes(ObjectName name, String[] attributes)
throws InstanceNotFoundException, ReflectionException {
try {
- return super.getAttributes(name, attributes);
+ final String[] authorized =
+ checkAttributes(name,attributes,"getAttribute");
+ final AttributeList attrList =
+ super.getAttributes(name,authorized);
+ return attrList;
} catch (IOException ex) {
throw handleIOException(ex,"getAttributes",name,attributes);
}
@@ -172,18 +184,19 @@ public abstract class HandlerInterceptor
}
}
- // From MBeanServer: catch & handles IOException
+ // From MBeanServerConnection: catch & handles IOException
@Override
public void removeNotificationListener(ObjectName name, ObjectName listener)
throws InstanceNotFoundException, ListenerNotFoundException {
try {
- super.removeNotificationListener(name, listener);
+ check(name,null,"removeNotificationListener");
+ super.removeNotificationListener(name,listener);
} catch (IOException ex) {
throw handleIOException(ex,"removeNotificationListener",name,listener);
}
}
- // From MBeanServer: catch & handles IOException
+ // From MBeanServerConnection: catch & handles IOException
@Override
public String getDefaultDomain() {
try {
@@ -193,17 +206,19 @@ public abstract class HandlerInterceptor
}
}
- // From MBeanServer: catch & handles IOException
+ // From MBeanServerConnection: catch & handles IOException
@Override
public String[] getDomains() {
try {
- return super.getDomains();
+ check(null,null,"getDomains");
+ final String[] domains = super.getDomains();
+ return checkDomains(domains,"getDomains");
} catch (IOException ex) {
throw handleIOException(ex,"getDomains");
}
}
- // From MBeanServer: catch & handles IOException
+ // From MBeanServerConnection: catch & handles IOException
@Override
public Integer getMBeanCount() {
try {
@@ -213,64 +228,74 @@ public abstract class HandlerInterceptor
}
}
- // From MBeanServer: catch & handles IOException
+ // From MBeanServerConnection: catch & handles IOException
@Override
public void setAttribute(ObjectName name, Attribute attribute)
throws InstanceNotFoundException, AttributeNotFoundException,
InvalidAttributeValueException, MBeanException,
ReflectionException {
try {
- super.setAttribute(name, attribute);
+ check(name,
+ (attribute==null?null:attribute.getName()),
+ "setAttribute");
+ super.setAttribute(name,attribute);
} catch (IOException ex) {
throw handleIOException(ex,"setAttribute",name, attribute);
}
}
- // From MBeanServer: catch & handles IOException
+ // From MBeanServerConnection: catch & handles IOException
@Override
public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
- try {
- return super.queryNames(name, query);
+ if (name == null) name=ObjectName.WILDCARD;
+ try {
+ checkPattern(name,null,"queryNames");
+ return super.queryNames(name,query);
} catch (IOException ex) {
throw handleIOException(ex,"queryNames",name, query);
}
}
- // From MBeanServer: catch & handles IOException
+ // From MBeanServerConnection: catch & handles IOException
@Override
public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) {
- try {
- return super.queryMBeans(name, query);
+ if (name == null) name=ObjectName.WILDCARD;
+ try {
+ checkPattern(name,null,"queryMBeans");
+ return super.queryMBeans(name,query);
} catch (IOException ex) {
throw handleIOException(ex,"queryMBeans",name, query);
}
}
- // From MBeanServer: catch & handles IOException
+ // From MBeanServerConnection: catch & handles IOException
@Override
public boolean isInstanceOf(ObjectName name, String className)
throws InstanceNotFoundException {
try {
+ check(name, null, "isInstanceOf");
return super.isInstanceOf(name, className);
} catch (IOException ex) {
throw handleIOException(ex,"isInstanceOf",name, className);
}
}
- // From MBeanServer: catch & handles IOException
+ // From MBeanServerConnection: catch & handles IOException
@Override
public ObjectInstance createMBean(String className, ObjectName name)
throws ReflectionException, InstanceAlreadyExistsException,
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException {
try {
+ checkCreate(name, className, "instantiate");
+ checkCreate(name, className, "registerMBean");
return super.createMBean(className, name);
} catch (IOException ex) {
throw handleIOException(ex,"createMBean",className, name);
}
}
- // From MBeanServer: catch & handles IOException
+ // From MBeanServerConnection: catch & handles IOException
@Override
public ObjectInstance createMBean(String className, ObjectName name,
ObjectName loaderName)
@@ -278,30 +303,34 @@ public abstract class HandlerInterceptor
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException, InstanceNotFoundException {
try {
+ checkCreate(name, className, "instantiate");
+ checkCreate(name, className, "registerMBean");
return super.createMBean(className, name, loaderName);
} catch (IOException ex) {
throw handleIOException(ex,"createMBean",className, name, loaderName);
}
}
- // From MBeanServer: catch & handles IOException
+ // From MBeanServerConnection: catch & handles IOException
@Override
public Object getAttribute(ObjectName name, String attribute)
throws MBeanException, AttributeNotFoundException,
InstanceNotFoundException, ReflectionException {
try {
+ check(name, attribute, "getAttribute");
return super.getAttribute(name, attribute);
} catch (IOException ex) {
throw handleIOException(ex,"getAttribute",name, attribute);
}
}
- // From MBeanServer: catch & handles IOException
+ // From MBeanServerConnection: catch & handles IOException
@Override
public void removeNotificationListener(ObjectName name, ObjectName listener,
NotificationFilter filter, Object handback)
throws InstanceNotFoundException, ListenerNotFoundException {
try {
+ check(name,null,"removeNotificationListener");
super.removeNotificationListener(name, listener, filter, handback);
} catch (IOException ex) {
throw handleIOException(ex,"removeNotificationListener",name,
@@ -309,13 +338,14 @@ public abstract class HandlerInterceptor
}
}
- // From MBeanServer: catch & handles IOException
+ // From MBeanServerConnection: catch & handles IOException
@Override
public void removeNotificationListener(ObjectName name,
NotificationListener listener, NotificationFilter filter,
Object handback)
throws InstanceNotFoundException, ListenerNotFoundException {
try {
+ check(name,null,"removeNotificationListener");
super.removeNotificationListener(name, listener, filter, handback);
} catch (IOException ex) {
throw handleIOException(ex,"removeNotificationListener",name,
@@ -323,12 +353,13 @@ public abstract class HandlerInterceptor
}
}
- // From MBeanServer: catch & handles IOException
+ // From MBeanServerConnection: catch & handles IOException
@Override
public void removeNotificationListener(ObjectName name,
NotificationListener listener)
throws InstanceNotFoundException, ListenerNotFoundException {
try {
+ check(name,null,"removeNotificationListener");
super.removeNotificationListener(name, listener);
} catch (IOException ex) {
throw handleIOException(ex,"removeNotificationListener",name,
@@ -336,12 +367,13 @@ public abstract class HandlerInterceptor
}
}
- // From MBeanServer: catch & handles IOException
+ // From MBeanServerConnection: catch & handles IOException
@Override
public void addNotificationListener(ObjectName name,
NotificationListener listener, NotificationFilter filter,
Object handback) throws InstanceNotFoundException {
try {
+ check(name,null,"addNotificationListener");
super.addNotificationListener(name, listener, filter, handback);
} catch (IOException ex) {
throw handleIOException(ex,"addNotificationListener",name,
@@ -349,12 +381,13 @@ public abstract class HandlerInterceptor
}
}
- // From MBeanServer: catch & handles IOException
+ // From MBeanServerConnection: catch & handles IOException
@Override
public void addNotificationListener(ObjectName name, ObjectName listener,
NotificationFilter filter, Object handback)
throws InstanceNotFoundException {
try {
+ check(name,null,"addNotificationListener");
super.addNotificationListener(name, listener, filter, handback);
} catch (IOException ex) {
throw handleIOException(ex,"addNotificationListener",name,
@@ -362,7 +395,7 @@ public abstract class HandlerInterceptor
}
}
- // From MBeanServer: catch & handles IOException
+ // From MBeanServerConnection: catch & handles IOException
@Override
public boolean isRegistered(ObjectName name) {
try {
@@ -372,41 +405,44 @@ public abstract class HandlerInterceptor
}
}
- // From MBeanServer: catch & handles IOException
+ // From MBeanServerConnection: catch & handles IOException
@Override
public void unregisterMBean(ObjectName name)
throws InstanceNotFoundException, MBeanRegistrationException {
try {
+ check(name, null, "unregisterMBean");
super.unregisterMBean(name);
} catch (IOException ex) {
throw handleIOException(ex,"unregisterMBean",name);
}
}
- // From MBeanServer: catch & handles IOException
+ // From MBeanServerConnection: catch & handles IOException
@Override
public MBeanInfo getMBeanInfo(ObjectName name)
throws InstanceNotFoundException, IntrospectionException,
ReflectionException {
try {
+ check(name, null, "getMBeanInfo");
return super.getMBeanInfo(name);
} catch (IOException ex) {
throw handleIOException(ex,"getMBeanInfo",name);
}
}
- // From MBeanServer: catch & handles IOException
+ // From MBeanServerConnection: catch & handles IOException
@Override
public ObjectInstance getObjectInstance(ObjectName name)
throws InstanceNotFoundException {
try {
+ check(name, null, "getObjectInstance");
return super.getObjectInstance(name);
} catch (IOException ex) {
throw handleIOException(ex,"getObjectInstance",name);
}
}
- // From MBeanServer: catch & handles IOException
+ // From MBeanServerConnection: catch & handles IOException
@Override
public ObjectInstance createMBean(String className, ObjectName name,
Object[] params, String[] signature)
@@ -414,6 +450,8 @@ public abstract class HandlerInterceptor
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException {
try {
+ checkCreate(name, className, "instantiate");
+ checkCreate(name, className, "registerMBean");
return super.createMBean(className, name, params, signature);
} catch (IOException ex) {
throw handleIOException(ex,"createMBean",className, name,
@@ -421,7 +459,7 @@ public abstract class HandlerInterceptor
}
}
- // From MBeanServer: catch & handles IOException
+ // From MBeanServerConnection: catch & handles IOException
@Override
public ObjectInstance createMBean(String className, ObjectName name,
ObjectName loaderName, Object[] params, String[] signature)
@@ -429,6 +467,8 @@ public abstract class HandlerInterceptor
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException, InstanceNotFoundException {
try {
+ checkCreate(name, className, "instantiate");
+ checkCreate(name, className, "registerMBean");
return super.createMBean(className, name, loaderName, params,
signature);
} catch (IOException ex) {
@@ -437,23 +477,26 @@ public abstract class HandlerInterceptor
}
}
- // From MBeanServer: catch & handles IOException
+ // From MBeanServerConnection: catch & handles IOException
@Override
public AttributeList setAttributes(ObjectName name,AttributeList attributes)
throws InstanceNotFoundException, ReflectionException {
try {
- return super.setAttributes(name, attributes);
+ final AttributeList authorized =
+ checkAttributes(name, attributes, "setAttribute");
+ return super.setAttributes(name, authorized);
} catch (IOException ex) {
throw handleIOException(ex,"setAttributes",name, attributes);
}
}
- // From MBeanServer: catch & handles IOException
+ // From MBeanServerConnection: catch & handles IOException
@Override
public Object invoke(ObjectName name, String operationName, Object[] params,
String[] signature)
throws InstanceNotFoundException, MBeanException, ReflectionException {
try {
+ check(name, operationName, "invoke");
return super.invoke(name, operationName, params, signature);
} catch (IOException ex) {
throw handleIOException(ex,"invoke",name, operationName,
@@ -574,4 +617,118 @@ public abstract class HandlerInterceptor
"Not supported in this namespace: "+namespace));
}
+ /**
+ * A result might be excluded for security reasons.
+ */
+ @Override
+ boolean excludesFromResult(ObjectName targetName, String queryMethod) {
+ return !checkQuery(targetName, queryMethod);
+ }
+
+
+ //----------------------------------------------------------------------
+ // Hooks for checking permissions
+ //----------------------------------------------------------------------
+
+ /**
+ * This method is a hook to implement permission checking in subclasses.
+ * 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.
+ * @throws SecurityException if the caller doesn't have the permission
+ * to perform the given action on the MBean pointed to
+ * by routingName.
+ */
+ abstract void check(ObjectName routingName,
+ String member, String action);
+
+ // called in createMBean and registerMBean
+ abstract void checkCreate(ObjectName routingName, String className,
+ String action);
+
+ /**
+ * 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}.
+ *
+ * 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.
+ */
+ abstract boolean checkQuery(ObjectName routingName, String action);
+
+ /**
+ * This method is a hook to implement permission checking in subclasses.
+ *
+ * @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}.
+ * @throws SecurityException if the caller doesn't have the permission
+ * to perform {@code action} on the MBean pointed to by routingName.
+ */
+ abstract String[] checkAttributes(ObjectName routingName,
+ String[] attributes, String action);
+
+ /**
+ * This method is a hook to implement permission checking in subclasses.
+ *
+ * @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}.
+ * @throws SecurityException if the caller doesn't have the permission
+ * to perform {@code action} on the MBean pointed to by routingName.
+ */
+ abstract AttributeList checkAttributes(ObjectName routingName,
+ AttributeList attributes, String action);
+
+ /**
+ * 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;
+ }
+
+ // A priori check for queryNames/queryMBeans/
+ 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.
+ // We only check that we have the permission requested for 'action'.
+ check(null,null,action);
+ }
+
+
+
}
--- a/src/share/classes/com/sun/jmx/namespace/JMXNamespaceUtils.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/com/sun/jmx/namespace/JMXNamespaceUtils.java Mon Sep 22 22:37:31 2008 -0700
@@ -29,7 +29,6 @@ import com.sun.jmx.defaults.JmxPropertie
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.NotificationFilt
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,24 +67,8 @@ 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.
--- a/src/share/classes/com/sun/jmx/namespace/NamespaceInterceptor.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/com/sun/jmx/namespace/NamespaceInterceptor.java Mon Sep 22 22:37:31 2008 -0700
@@ -25,22 +25,15 @@ package com.sun.jmx.namespace;
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.JMXNam
*/
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;
@@ -67,21 +54,6 @@ public class NamespaceInterceptor extend
private final String serverName;
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
@@ -102,164 +74,6 @@ public class NamespaceInterceptor extend
public String toString() {
return this.getClass().getName()+"(parent="+serverName+
", 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;
}
/**
@@ -281,29 +95,9 @@ public class NamespaceInterceptor extend
* (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");
}
@@ -317,24 +111,6 @@ public class NamespaceInterceptor extend
protected MBeanServer getServerForLoading() {
// don't want to send probe on getClassLoader/getClassLoaderFor
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
--- a/src/share/classes/com/sun/jmx/namespace/RoutingConnectionProxy.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/com/sun/jmx/namespace/RoutingConnectionProxy.java Mon Sep 22 22:37:31 2008 -0700
@@ -45,6 +45,9 @@ import javax.management.namespace.JMXNam
* </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);
}
}
--- a/src/share/classes/com/sun/jmx/namespace/RoutingMBeanServerConnection.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/com/sun/jmx/namespace/RoutingMBeanServerConnection.java Mon Sep 22 22:37:31 2008 -0700
@@ -83,18 +83,32 @@ public abstract class RoutingMBeanServer
}
/**
- * 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,88 +156,15 @@ public abstract class RoutingMBeanServer
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;
- } 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) {
+ return source().getAttributes(sourceName, attributes);
+ } catch (RuntimeException ex) {
+ throw makeCompliantRuntimeException(ex);
+ }
}
// from MBeanServerConnection
@@ -233,7 +174,6 @@ public abstract class RoutingMBeanServer
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 RoutingMBeanServer
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 RoutingMBeanServer
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 RoutingMBeanServer
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 RoutingMBeanServer
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 RoutingMBeanServer
// 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 RoutingMBeanServer
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 RoutingMBeanServer
// 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 RoutingMBeanServer
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 RoutingMBeanServer
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 RoutingMBeanServer
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 RoutingMBeanServer
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 RoutingMBeanServer
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 RoutingMBeanServer
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 RoutingMBeanServer
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 RoutingMBeanServer
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 RoutingMBeanServer
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 RoutingMBeanServer
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 RoutingMBeanServer
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 RoutingMBeanServer
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 RoutingMBeanServer
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 RoutingMBeanServer
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 RoutingMBeanServer
// 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,37 +531,37 @@ public abstract class RoutingMBeanServer
// from MBeanServerConnection
public String[] getDomains() throws IOException {
try {
- check(null,null,"getDomains");
- final String[] domains = source().getDomains();
- return checkDomains(domains,"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}
+ return source().getDomains();
+ } catch (RuntimeException ex) {
+ throw makeCompliantRuntimeException(ex);
+ }
+ }
+
+ // from MBeanServerConnection
+ public String getDefaultDomain() throws IOException {
+ try {
+ return source().getDefaultDomain();
+ } catch (RuntimeException ex) {
+ throw makeCompliantRuntimeException(ex);
+ }
+ }
+
+ /**
+ * 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 domains The domains to return.
- * @param action "getDomains"
- * @return a filtered list of domains.
+ * @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.
*/
- String[] checkDomains(String[] domains, String action) {
- return domains;
- }
-
- // from MBeanServerConnection
- public String getDefaultDomain() throws IOException {
- try {
- return source().getDefaultDomain();
- } catch (RuntimeException ex) {
- throw makeCompliantRuntimeException(ex);
- }
+ boolean excludesFromResult(ObjectName targetName, String queryMethod) {
+ return false;
}
}
--- a/src/share/classes/com/sun/jmx/namespace/RoutingProxy.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/com/sun/jmx/namespace/RoutingProxy.java Mon Sep 22 22:37:31 2008 -0700
@@ -30,31 +30,110 @@ import java.util.logging.Level;
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 ext
throw x;
} catch (MBeanException ex) {
throw new IOException("Failed to get "+attributeName+": "+
- ex.getMessage(),
- ex.getTargetException());
- } catch (AttributeNotFoundException ex) {
+ ex.getCause(),
+ ex.getCause());
+ } catch (Exception ex) {
throw new IOException("Failed to get "+attributeName+": "+
- ex.getMessage(),ex);
- } catch (InstanceNotFoundException 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 ext
(" 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);
+ }
}
--- a/src/share/classes/com/sun/jmx/namespace/RoutingServerProxy.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/com/sun/jmx/namespace/RoutingServerProxy.java Mon Sep 22 22:37:31 2008 -0700
@@ -69,6 +69,9 @@ import javax.management.namespace.JMXNam
*
* @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);
}
}
--- a/src/share/classes/com/sun/jmx/remote/internal/ClientCommunicatorAdmin.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/com/sun/jmx/remote/internal/ClientCommunicatorAdmin.java Mon Sep 22 22:37:31 2008 -0700
@@ -32,13 +32,15 @@ import com.sun.jmx.remote.util.EnvHelp;
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
--- a/src/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java Mon Sep 22 22:37:31 2008 -0700
@@ -290,28 +290,6 @@ public abstract class ClientNotifForward
infoList.clear();
- if (currentFetchThread == Thread.currentThread()) {
- /* we do not need to stop the fetching thread, because this thread is
- used to do restarting and it will not be used to do fetching during
- the re-registering the listeners.*/
- return tmp;
- }
-
- while (state == STARTING) {
- try {
- wait();
- } catch (InterruptedException ire) {
- IOException ioe = new IOException(ire.toString());
- EnvHelp.initCause(ioe, ire);
-
- throw ioe;
- }
- }
-
- if (state == STARTED) {
- setState(STOPPING);
- }
-
return tmp;
}
@@ -353,8 +331,9 @@ public abstract class ClientNotifForward
beingReconnected = false;
notifyAll();
- if (currentFetchThread == Thread.currentThread()) {
- // no need to init, simply get the id
+ if (currentFetchThread == Thread.currentThread() ||
+ state == STARTING || state == STARTED) { // doing or waiting reconnection
+ // only update mbeanRemovedNotifID
try {
mbeanRemovedNotifID = addListenerForMBeanRemovedNotif();
} catch (Exception e) {
@@ -366,12 +345,23 @@ public abstract class ClientNotifForward
logger.trace("init", msg, e);
}
}
- } else if (listenerInfos.length > 0) { // old listeners re-registered
- init(true);
- } else if (infoList.size() > 0) {
- // but new listeners registered during reconnection
- init(false);
- }
+ } else {
+ while (state == STOPPING) {
+ try {
+ wait();
+ } catch (InterruptedException ire) {
+ IOException ioe = new IOException(ire.toString());
+ EnvHelp.initCause(ioe, ire);
+ throw ioe;
+ }
+ }
+
+ if (listenerInfos.length > 0) { // old listeners are re-added
+ init(true); // not update clientSequenceNumber
+ } else if (infoList.size() > 0) { // only new listeners added during reconnection
+ init(false); // need update clientSequenceNumber
+ }
+ }
}
public synchronized void terminate() {
@@ -486,6 +476,15 @@ public abstract class ClientNotifForward
if (nr == null || shouldStop()) {
// tell that the thread is REALLY stopped
setState(STOPPED);
+
+ try {
+ removeListenerForMBeanRemovedNotif(mbeanRemovedNotifID);
+ } catch (Exception e) {
+ if (logger.traceOn()) {
+ logger.trace("NotifFetcher-run",
+ "removeListenerForMBeanRemovedNotif", e);
+ }
+ }
} else {
executor.execute(this);
}
--- a/src/share/classes/java/lang/AbstractStringBuilder.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/java/lang/AbstractStringBuilder.java Mon Sep 22 22:37:31 2008 -0700
@@ -42,7 +42,7 @@ abstract class AbstractStringBuilder imp
/**
* The value is used for character storage.
*/
- char value[];
+ char[] value;
/**
* The count is the number of characters used.
@@ -333,8 +333,7 @@ abstract class AbstractStringBuilder imp
* <code>dst.length</code>
* </ul>
*/
- public void getChars(int srcBegin, int srcEnd, char dst[],
- int dstBegin)
+ public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
{
if (srcBegin < 0)
throw new StringIndexOutOfBoundsException(srcBegin);
@@ -366,14 +365,14 @@ abstract class AbstractStringBuilder imp
}
/**
- * Appends the string representation of the <code>Object</code>
- * argument.
- * <p>
- * The argument is converted to a string as if by the method
- * <code>String.valueOf</code>, and the characters of that
- * string are then appended to this sequence.
- *
- * @param obj an <code>Object</code>.
+ * Appends the string representation of the {@code Object} argument.
+ * <p>
+ * The overall effect is exactly as if the argument were converted
+ * to a string by the method {@link String#valueOf(Object)},
+ * and the characters of that string were then
+ * {@link #append(String) appended} to this character sequence.
+ *
+ * @param obj an {@code Object}.
* @return a reference to this object.
*/
public AbstractStringBuilder append(Object obj) {
@@ -383,17 +382,17 @@ abstract class AbstractStringBuilder imp
/**
* Appends the specified string to this character sequence.
* <p>
- * The characters of the <code>String</code> argument are appended, in
+ * The characters of the {@code String} argument are appended, in
* order, increasing the length of this sequence by the length of the
- * argument. If <code>str</code> is <code>null</code>, then the four
- * characters <code>"null"</code> are appended.
+ * argument. If {@code str} is {@code null}, then the four
+ * characters {@code "null"} are appended.
* <p>
* Let <i>n</i> be the length of this character sequence just prior to
- * execution of the <code>append</code> method. Then the character at
+ * execution of the {@code append} method. Then the character at
* index <i>k</i> in the new character sequence is equal to the character
* at index <i>k</i> in the old character sequence, if <i>k</i> is less
* than <i>n</i>; otherwise, it is equal to the character at index
- * <i>k-n</i> in the argument <code>str</code>.
+ * <i>k-n</i> in the argument {@code str}.
*
* @param str a string.
* @return a reference to this object.
@@ -435,33 +434,33 @@ abstract class AbstractStringBuilder imp
}
/**
- * Appends a subsequence of the specified <code>CharSequence</code> to this
+ * Appends a subsequence of the specified {@code CharSequence} to this
* sequence.
* <p>
- * Characters of the argument <code>s</code>, starting at
- * index <code>start</code>, are appended, in order, to the contents of
- * this sequence up to the (exclusive) index <code>end</code>. The length
- * of this sequence is increased by the value of <code>end - start</code>.
+ * Characters of the argument {@code s}, starting at
+ * index {@code start}, are appended, in order, to the contents of
+ * this sequence up to the (exclusive) index {@code end}. The length
+ * of this sequence is increased by the value of {@code end - start}.
* <p>
* Let <i>n</i> be the length of this character sequence just prior to
- * execution of the <code>append</code> method. Then the character at
+ * execution of the {@code append} method. Then the character at
* index <i>k</i> in this character sequence becomes equal to the
* character at index <i>k</i> in this sequence, if <i>k</i> is less than
* <i>n</i>; otherwise, it is equal to the character at index
- * <i>k+start-n</i> in the argument <code>s</code>.
- * <p>
- * If <code>s</code> is <code>null</code>, then this method appends
+ * <i>k+start-n</i> in the argument {@code s}.
+ * <p>
+ * If {@code s} is {@code null}, then this method appends
* characters as if the s parameter was a sequence containing the four
- * characters <code>"null"</code>.
+ * characters {@code "null"}.
*
* @param s the sequence to append.
* @param start the starting index of the subsequence to be appended.
* @param end the end index of the subsequence to be appended.
* @return a reference to this object.
* @throws IndexOutOfBoundsException if
- * <code>start</code> or <code>end</code> are negative, or
- * <code>start</code> is greater than <code>end</code> or
- * <code>end</code> is greater than <code>s.length()</code>
+ * {@code start} is negative, or
+ * {@code start} is greater than {@code end} or
+ * {@code end} is greater than {@code s.length()}
*/
public AbstractStringBuilder append(CharSequence s, int start, int end) {
if (s == null)
@@ -483,22 +482,22 @@ abstract class AbstractStringBuilder imp
}
/**
- * Appends the string representation of the <code>char</code> array
+ * Appends the string representation of the {@code char} array
* argument to this sequence.
* <p>
* The characters of the array argument are appended, in order, to
* the contents of this sequence. The length of this sequence
* increases by the length of the argument.
* <p>
- * The overall effect is exactly as if the argument were converted to
- * a string by the method {@link String#valueOf(char[])} and the
- * characters of that string were then {@link #append(String) appended}
- * to this character sequence.
+ * The overall effect is exactly as if the argument were converted
+ * to a string by the method {@link String#valueOf(char[])},
+ * and the characters of that string were then
+ * {@link #append(String) appended} to this character sequence.
*
* @param str the characters to be appended.
* @return a reference to this object.
*/
- public AbstractStringBuilder append(char str[]) {
+ public AbstractStringBuilder append(char[] str) {
int newCount = count + str.length;
if (newCount > value.length)
expandCapacity(newCount);
@@ -509,22 +508,25 @@ abstract class AbstractStringBuilder imp
/**
* Appends the string representation of a subarray of the
- * <code>char</code> array argument to this sequence.
- * <p>
- * Characters of the <code>char</code> array <code>str</code>, starting at
- * index <code>offset</code>, are appended, in order, to the contents
+ * {@code char} array argument to this sequence.
+ * <p>
+ * Characters of the {@code char} array {@code str}, starting at
+ * index {@code offset}, are appended, in order, to the contents
* of this sequence. The length of this sequence increases
- * by the value of <code>len</code>.
- * <p>
- * The overall effect is exactly as if the arguments were converted to
- * a string by the method {@link String#valueOf(char[],int,int)} and the
- * characters of that string were then {@link #append(String) appended}
- * to this character sequence.
+ * by the value of {@code len}.
+ * <p>
+ * The overall effect is exactly as if the arguments were converted
+ * to a string by the method {@link String#valueOf(char[],int,int)},
+ * and the characters of that string were then
+ * {@link #append(String) appended} to this character sequence.
*
* @param str the characters to be appended.
- * @param offset the index of the first <code>char</code> to append.
- * @param len the number of <code>char</code>s to append.
+ * @param offset the index of the first {@code char} to append.
+ * @param len the number of {@code char}s to append.
* @return a reference to this object.
+ * @throws IndexOutOfBoundsException
+ * if {@code offset < 0} or {@code len < 0}
+ * or {@code offset+len > str.length}
*/
public AbstractStringBuilder append(char str[], int offset, int len) {
int newCount = count + len;
@@ -536,14 +538,15 @@ abstract class AbstractStringBuilder imp
}
/**
- * Appends the string representation of the <code>boolean</code>
+ * Appends the string representation of the {@code boolean}
* argument to the sequence.
* <p>
- * The argument is converted to a string as if by the method
- * <code>String.valueOf</code>, and the characters of that
- * string are then appended to this sequence.
- *
- * @param b a <code>boolean</code>.
+ * The overall effect is exactly as if the argument were converted
+ * to a string by the method {@link String#valueOf(boolean)},
+ * and the characters of that string were then
+ * {@link #append(String) appended} to this character sequence.
+ *
+ * @param b a {@code boolean}.
* @return a reference to this object.
*/
public AbstractStringBuilder append(boolean b) {
@@ -569,18 +572,18 @@ abstract class AbstractStringBuilder imp
}
/**
- * Appends the string representation of the <code>char</code>
+ * Appends the string representation of the {@code char}
* argument to this sequence.
* <p>
* The argument is appended to the contents of this sequence.
- * The length of this sequence increases by <code>1</code>.
- * <p>
- * The overall effect is exactly as if the argument were converted to
- * a string by the method {@link String#valueOf(char)} and the character
- * in that string were then {@link #append(String) appended} to this
- * character sequence.
- *
- * @param c a <code>char</code>.
+ * The length of this sequence increases by {@code 1}.
+ * <p>
+ * The overall effect is exactly as if the argument were converted
+ * to a string by the method {@link String#valueOf(char)},
+ * and the character in that string were then
+ * {@link #append(String) appended} to this character sequence.
+ *
+ * @param c a {@code char}.
* @return a reference to this object.
*/
public AbstractStringBuilder append(char c) {
@@ -592,14 +595,15 @@ abstract class AbstractStringBuilder imp
}
/**
- * Appends the string representation of the <code>int</code>
+ * Appends the string representation of the {@code int}
* argument to this sequence.
* <p>
- * The argument is converted to a string as if by the method
- * <code>String.valueOf</code>, and the characters of that
- * string are then appended to this sequence.
- *
- * @param i an <code>int</code>.
+ * The overall effect is exactly as if the argument were converted
+ * to a string by the method {@link String#valueOf(int)},
+ * and the characters of that string were then
+ * {@link #append(String) appended} to this character sequence.
+ *
+ * @param i an {@code int}.
* @return a reference to this object.
*/
public AbstractStringBuilder append(int i) {
@@ -618,14 +622,15 @@ abstract class AbstractStringBuilder imp
}
/**
- * Appends the string representation of the <code>long</code>
+ * Appends the string representation of the {@code long}
* argument to this sequence.
* <p>
- * The argument is converted to a string as if by the method
- * <code>String.valueOf</code>, and the characters of that
- * string are then appended to this sequence.
- *
- * @param l a <code>long</code>.
+ * The overall effect is exactly as if the argument were converted
+ * to a string by the method {@link String#valueOf(long)},
+ * and the characters of that string were then
+ * {@link #append(String) appended} to this character sequence.
+ *
+ * @param l a {@code long}.
* @return a reference to this object.
*/
public AbstractStringBuilder append(long l) {
@@ -644,14 +649,15 @@ abstract class AbstractStringBuilder imp
}
/**
- * Appends the string representation of the <code>float</code>
+ * Appends the string representation of the {@code float}
* argument to this sequence.
* <p>
- * The argument is converted to a string as if by the method
- * <code>String.valueOf</code>, and the characters of that
- * string are then appended to this string sequence.
- *
- * @param f a <code>float</code>.
+ * The overall effect is exactly as if the argument were converted
+ * to a string by the method {@link String#valueOf(float)},
+ * and the characters of that string were then
+ * {@link #append(String) appended} to this character sequence.
+ *
+ * @param f a {@code float}.
* @return a reference to this object.
*/
public AbstractStringBuilder append(float f) {
@@ -660,14 +666,15 @@ abstract class AbstractStringBuilder imp
}
/**
- * Appends the string representation of the <code>double</code>
+ * Appends the string representation of the {@code double}
* argument to this sequence.
* <p>
- * The argument is converted to a string as if by the method
- * <code>String.valueOf</code>, and the characters of that
- * string are then appended to this sequence.
- *
- * @param d a <code>double</code>.
+ * The overall effect is exactly as if the argument were converted
+ * to a string by the method {@link String#valueOf(double)},
+ * and the characters of that string were then
+ * {@link #append(String) appended} to this character sequence.
+ *
+ * @param d a {@code double}.
* @return a reference to this object.
*/
public AbstractStringBuilder append(double d) {
@@ -677,17 +684,17 @@ abstract class AbstractStringBuilder imp
/**
* Removes the characters in a substring of this sequence.
- * The substring begins at the specified <code>start</code> and extends to
- * the character at index <code>end - 1</code> or to the end of the
+ * The substring begins at the specified {@code start} and extends to
+ * the character at index {@code end - 1} or to the end of the
* sequence if no such character exists. If
- * <code>start</code> is equal to <code>end</code>, no changes are made.
+ * {@code start} is equal to {@code end}, no changes are made.
*
* @param start The beginning index, inclusive.
* @param end The ending index, exclusive.
* @return This object.
- * @throws StringIndexOutOfBoundsException if <code>start</code>
- * is negative, greater than <code>length()</code>, or
- * greater than <code>end</code>.
+ * @throws StringIndexOutOfBoundsException if {@code start}
+ * is negative, greater than {@code length()}, or
+ * greater than {@code end}.
*/
public AbstractStringBuilder delete(int start, int end) {
if (start < 0)
@@ -705,7 +712,7 @@ abstract class AbstractStringBuilder imp
}
/**
- * Appends the string representation of the <code>codePoint</code>
+ * Appends the string representation of the {@code codePoint}
* argument to this sequence.
*
* <p> The argument is appended to the contents of this sequence.
@@ -713,15 +720,15 @@ abstract class AbstractStringBuilder imp
* {@link Character#charCount(int) Character.charCount(codePoint)}.
*
* <p> The overall effect is exactly as if the argument were
- * converted to a <code>char</code> array by the method {@link
- * Character#toChars(int)} and the character in that array were
- * then {@link #append(char[]) appended} to this character
+ * converted to a {@code char} array by the method
+ * {@link Character#toChars(int)} and the character in that array
+ * were then {@link #append(char[]) appended} to this character
* sequence.
*
* @param codePoint a Unicode code point
* @return a reference to this object.
* @exception IllegalArgumentException if the specified
- * <code>codePoint</code> isn't a valid Unicode code point
+ * {@code codePoint} isn't a valid Unicode code point
*/
public AbstractStringBuilder appendCodePoint(int codePoint) {
if (!Character.isValidCodePoint(codePoint)) {
@@ -879,27 +886,27 @@ abstract class AbstractStringBuilder imp
}
/**
- * Inserts the string representation of a subarray of the <code>str</code>
+ * Inserts the string representation of a subarray of the {@code str}
* array argument into this sequence. The subarray begins at the
- * specified <code>offset</code> and extends <code>len</code> <code>char</code>s.
+ * specified {@code offset} and extends {@code len} {@code char}s.
* The characters of the subarray are inserted into this sequence at
- * the position indicated by <code>index</code>. The length of this
- * sequence increases by <code>len</code> <code>char</code>s.
+ * the position indicated by {@code index}. The length of this
+ * sequence increases by {@code len} {@code char}s.
*
* @param index position at which to insert subarray.
- * @param str A <code>char</code> array.
- * @param offset the index of the first <code>char</code> in subarray to
+ * @param str A {@code char} array.
+ * @param offset the index of the first {@code char} in subarray to
* be inserted.
- * @param len the number of <code>char</code>s in the subarray to
+ * @param len the number of {@code char}s in the subarray to
* be inserted.
* @return This object
- * @throws StringIndexOutOfBoundsException if <code>index</code>
- * is negative or greater than <code>length()</code>, or
- * <code>offset</code> or <code>len</code> are negative, or
- * <code>(offset+len)</code> is greater than
- * <code>str.length</code>.
- */
- public AbstractStringBuilder insert(int index, char str[], int offset,
+ * @throws StringIndexOutOfBoundsException if {@code index}
+ * is negative or greater than {@code length()}, or
+ * {@code offset} or {@code len} are negative, or
+ * {@code (offset+len)} is greater than
+ * {@code str.length}.
+ */
+ public AbstractStringBuilder insert(int index, char[] str, int offset,
int len)
{
if ((index < 0) || (index > length()))
@@ -918,20 +925,21 @@ abstract class AbstractStringBuilder imp
}
/**
- * Inserts the string representation of the <code>Object</code>
+ * Inserts the string representation of the {@code Object}
* argument into this character sequence.
* <p>
- * The second argument is converted to a string as if by the method
- * <code>String.valueOf</code>, and the characters of that
- * string are then inserted into this sequence at the indicated
- * offset.
- * <p>
- * The offset argument must be greater than or equal to
- * <code>0</code>, and less than or equal to the length of this
- * sequence.
+ * The overall effect is exactly as if the second argument were
+ * converted to a string by the method {@link String#valueOf(Object)},
+ * and the characters of that string were then
+ * {@link #insert(int,String) inserted} into this character
+ * sequence at the indicated offset.
+ * <p>
+ * The {@code offset} argument must be greater than or equal to
+ * {@code 0}, and less than or equal to the {@linkplain #length() length}
+ * of this sequence.
*
* @param offset the offset.
- * @param obj an <code>Object</code>.
+ * @param obj an {@code Object}.
* @return a reference to this object.
* @throws StringIndexOutOfBoundsException if the offset is invalid.
*/
@@ -942,28 +950,28 @@ abstract class AbstractStringBuilder imp
/**
* Inserts the string into this character sequence.
* <p>
- * The characters of the <code>String</code> argument are inserted, in
+ * The characters of the {@code String} argument are inserted, in
* order, into this sequence at the indicated offset, moving up any
* characters originally above that position and increasing the length
* of this sequence by the length of the argument. If
- * <code>str</code> is <code>null</code>, then the four characters
- * <code>"null"</code> are inserted into this sequence.
+ * {@code str} is {@code null}, then the four characters
+ * {@code "null"} are inserted into this sequence.
* <p>
* The character at index <i>k</i> in the new character sequence is
* equal to:
* <ul>
* <li>the character at index <i>k</i> in the old character sequence, if
- * <i>k</i> is less than <code>offset</code>
- * <li>the character at index <i>k</i><code>-offset</code> in the
- * argument <code>str</code>, if <i>k</i> is not less than
- * <code>offset</code> but is less than <code>offset+str.length()</code>
- * <li>the character at index <i>k</i><code>-str.length()</code> in the
+ * <i>k</i> is less than {@code offset}
+ * <li>the character at index <i>k</i>{@code -offset} in the
+ * argument {@code str}, if <i>k</i> is not less than
+ * {@code offset} but is less than {@code offset+str.length()}
+ * <li>the character at index <i>k</i>{@code -str.length()} in the
* old character sequence, if <i>k</i> is not less than
- * <code>offset+str.length()</code>
+ * {@code offset+str.length()}
* </ul><p>
- * The offset argument must be greater than or equal to
- * <code>0</code>, and less than or equal to the length of this
- * sequence.
+ * The {@code offset} argument must be greater than or equal to
+ * {@code 0}, and less than or equal to the {@linkplain #length() length}
+ * of this sequence.
*
* @param offset the offset.
* @param str a string.
@@ -986,27 +994,30 @@ abstract class AbstractStringBuilder imp
}
/**
- * Inserts the string representation of the <code>char</code> array
+ * Inserts the string representation of the {@code char} array
* argument into this sequence.
* <p>
* The characters of the array argument are inserted into the
* contents of this sequence at the position indicated by
- * <code>offset</code>. The length of this sequence increases by
+ * {@code offset}. The length of this sequence increases by
* the length of the argument.
* <p>
- * The overall effect is exactly as if the argument were converted to
- * a string by the method {@link String#valueOf(char[])} and the
- * characters of that string were then
- * {@link #insert(int,String) inserted} into this
- * character sequence at the position indicated by
- * <code>offset</code>.
+ * The overall effect is exactly as if the second argument were
+ * converted to a string by the method {@link String#valueOf(char[])},
+ * and the characters of that string were then
+ * {@link #insert(int,String) inserted} into this character
+ * sequence at the indicated offset.
+ * <p>
+ * The {@code offset} argument must be greater than or equal to
+ * {@code 0}, and less than or equal to the {@linkplain #length() length}
+ * of this sequence.
*
* @param offset the offset.
* @param str a character array.
* @return a reference to this object.
* @throws StringIndexOutOfBoundsException if the offset is invalid.
*/
- public AbstractStringBuilder insert(int offset, char str[]) {
+ public AbstractStringBuilder insert(int offset, char[] str) {
if ((offset < 0) || (offset > length()))
throw new StringIndexOutOfBoundsException(offset);
int len = str.length;
@@ -1020,18 +1031,20 @@ abstract class AbstractStringBuilder imp
}
/**
- * Inserts the specified <code>CharSequence</code> into this sequence.
- * <p>
- * The characters of the <code>CharSequence</code> argument are inserted,
+ * Inserts the specified {@code CharSequence} into this sequence.
+ * <p>
+ * The characters of the {@code CharSequence} argument are inserted,
* in order, into this sequence at the indicated offset, moving up
* any characters originally above that position and increasing the length
* of this sequence by the length of the argument s.
* <p>
* The result of this method is exactly the same as if it were an
- * invocation of this object's insert(dstOffset, s, 0, s.length()) method.
- *
- * <p>If <code>s</code> is <code>null</code>, then the four characters
- * <code>"null"</code> are inserted into this sequence.
+ * invocation of this object's
+ * {@link #insert(int,CharSequence,int,int) insert}(dstOffset, s, 0, s.length())
+ * method.
+ *
+ * <p>If {@code s} is {@code null}, then the four characters
+ * {@code "null"} are inserted into this sequence.
*
* @param dstOffset the offset.
* @param s the sequence to be inserted
@@ -1047,51 +1060,51 @@ abstract class AbstractStringBuilder imp
}
/**
- * Inserts a subsequence of the specified <code>CharSequence</code> into
+ * Inserts a subsequence of the specified {@code CharSequence} into
* this sequence.
* <p>
- * The subsequence of the argument <code>s</code> specified by
- * <code>start</code> and <code>end</code> are inserted,
+ * The subsequence of the argument {@code s} specified by
+ * {@code start} and {@code end} are inserted,
* in order, into this sequence at the specified destination offset, moving
* up any characters originally above that position. The length of this
- * sequence is increased by <code>end - start</code>.
+ * sequence is increased by {@code end - start}.
* <p>
* The character at index <i>k</i> in this sequence becomes equal to:
* <ul>
* <li>the character at index <i>k</i> in this sequence, if
- * <i>k</i> is less than <code>dstOffset</code>
- * <li>the character at index <i>k</i><code>+start-dstOffset</code> in
- * the argument <code>s</code>, if <i>k</i> is greater than or equal to
- * <code>dstOffset</code> but is less than <code>dstOffset+end-start</code>
- * <li>the character at index <i>k</i><code>-(end-start)</code> in this
+ * <i>k</i> is less than {@code dstOffset}
+ * <li>the character at index <i>k</i>{@code +start-dstOffset} in
+ * the argument {@code s}, if <i>k</i> is greater than or equal to
+ * {@code dstOffset} but is less than {@code dstOffset+end-start}
+ * <li>the character at index <i>k</i>{@code -(end-start)} in this
* sequence, if <i>k</i> is greater than or equal to
- * <code>dstOffset+end-start</code>
+ * {@code dstOffset+end-start}
* </ul><p>
- * The dstOffset argument must be greater than or equal to
- * <code>0</code>, and less than or equal to the length of this
- * sequence.
+ * The {@code dstOffset} argument must be greater than or equal to
+ * {@code 0}, and less than or equal to the {@linkplain #length() length}
+ * of this sequence.
* <p>The start argument must be nonnegative, and not greater than
- * <code>end</code>.
+ * {@code end}.
* <p>The end argument must be greater than or equal to
- * <code>start</code>, and less than or equal to the length of s.
- *
- * <p>If <code>s</code> is <code>null</code>, then this method inserts
+ * {@code start}, and less than or equal to the length of s.
+ *
+ * <p>If {@code s} is {@code null}, then this method inserts
* characters as if the s parameter was a sequence containing the four
- * characters <code>"null"</code>.
+ * characters {@code "null"}.
*
* @param dstOffset the offset in this sequence.
* @param s the sequence to be inserted.
* @param start the starting index of the subsequence to be inserted.
* @param end the end index of the subsequence to be inserted.
* @return a reference to this object.
- * @throws IndexOutOfBoundsException if <code>dstOffset</code>
- * is negative or greater than <code>this.length()</code>, or
- * <code>start</code> or <code>end</code> are negative, or
- * <code>start</code> is greater than <code>end</code> or
- * <code>end</code> is greater than <code>s.length()</code>
+ * @throws IndexOutOfBoundsException if {@code dstOffset}
+ * is negative or greater than {@code this.length()}, or
+ * {@code start} or {@code end} are negative, or
+ * {@code start} is greater than {@code end} or
+ * {@code end} is greater than {@code s.length()}
*/
public AbstractStringBuilder insert(int dstOffset, CharSequence s,
- int start, int end) {
+ int start, int end) {
if (s == null)
s = "null";
if ((dstOffset < 0) || (dstOffset > this.length()))
@@ -1115,20 +1128,21 @@ abstract class AbstractStringBuilder imp
}
/**
- * Inserts the string representation of the <code>boolean</code>
+ * Inserts the string representation of the {@code boolean}
* argument into this sequence.
* <p>
- * The second argument is converted to a string as if by the method
- * <code>String.valueOf</code>, and the characters of that
- * string are then inserted into this sequence at the indicated
- * offset.
- * <p>
- * The offset argument must be greater than or equal to
- * <code>0</code>, and less than or equal to the length of this
- * sequence.
+ * The overall effect is exactly as if the second argument were
+ * converted to a string by the method {@link String#valueOf(boolean)},
+ * and the characters of that string were then
+ * {@link #insert(int,String) inserted} into this character
+ * sequence at the indicated offset.
+ * <p>
+ * The {@code offset} argument must be greater than or equal to
+ * {@code 0}, and less than or equal to the {@linkplain #length() length}
+ * of this sequence.
*
* @param offset the offset.
- * @param b a <code>boolean</code>.
+ * @param b a {@code boolean}.
* @return a reference to this object.
* @throws StringIndexOutOfBoundsException if the offset is invalid.
*/
@@ -1137,25 +1151,21 @@ abstract class AbstractStringBuilder imp
}
/**
- * Inserts the string representation of the <code>char</code>
+ * Inserts the string representation of the {@code char}
* argument into this sequence.
* <p>
- * The second argument is inserted into the contents of this sequence
- * at the position indicated by <code>offset</code>. The length
- * of this sequence increases by one.
- * <p>
- * The overall effect is exactly as if the argument were converted to
- * a string by the method {@link String#valueOf(char)} and the character
- * in that string were then {@link #insert(int, String) inserted} into
- * this character sequence at the position indicated by
- * <code>offset</code>.
- * <p>
- * The offset argument must be greater than or equal to
- * <code>0</code>, and less than or equal to the length of this
- * sequence.
+ * The overall effect is exactly as if the second argument were
+ * converted to a string by the method {@link String#valueOf(char)},
+ * and the character in that string were then
+ * {@link #insert(int,String) inserted} into this character
+ * sequence at the indicated offset.
+ * <p>
+ * The {@code offset} argument must be greater than or equal to
+ * {@code 0}, and less than or equal to the {@linkplain #length() length}
+ * of this sequence.
*
* @param offset the offset.
- * @param c a <code>char</code>.
+ * @param c a {@code char}.
* @return a reference to this object.
* @throws IndexOutOfBoundsException if the offset is invalid.
*/
@@ -1170,20 +1180,21 @@ abstract class AbstractStringBuilder imp
}
/**
- * Inserts the string representation of the second <code>int</code>
+ * Inserts the string representation of the second {@code int}
* argument into this sequence.
* <p>
- * The second argument is converted to a string as if by the method
- * <code>String.valueOf</code>, and the characters of that
- * string are then inserted into this sequence at the indicated
- * offset.
- * <p>
- * The offset argument must be greater than or equal to
- * <code>0</code>, and less than or equal to the length of this
- * sequence.
+ * The overall effect is exactly as if the second argument were
+ * converted to a string by the method {@link String#valueOf(int)},
+ * and the characters of that string were then
+ * {@link #insert(int,String) inserted} into this character
+ * sequence at the indicated offset.
+ * <p>
+ * The {@code offset} argument must be greater than or equal to
+ * {@code 0}, and less than or equal to the {@linkplain #length() length}
+ * of this sequence.
*
* @param offset the offset.
- * @param i an <code>int</code>.
+ * @param i an {@code int}.
* @return a reference to this object.
* @throws StringIndexOutOfBoundsException if the offset is invalid.
*/
@@ -1192,20 +1203,21 @@ abstract class AbstractStringBuilder imp
}
/**
- * Inserts the string representation of the <code>long</code>
+ * Inserts the string representation of the {@code long}
* argument into this sequence.
* <p>
- * The second argument is converted to a string as if by the method
- * <code>String.valueOf</code>, and the characters of that
- * string are then inserted into this sequence at the position
- * indicated by <code>offset</code>.
- * <p>
- * The offset argument must be greater than or equal to
- * <code>0</code>, and less than or equal to the length of this
- * sequence.
+ * The overall effect is exactly as if the second argument were
+ * converted to a string by the method {@link String#valueOf(long)},
+ * and the characters of that string were then
+ * {@link #insert(int,String) inserted} into this character
+ * sequence at the indicated offset.
+ * <p>
+ * The {@code offset} argument must be greater than or equal to
+ * {@code 0}, and less than or equal to the {@linkplain #length() length}
+ * of this sequence.
*
* @param offset the offset.
- * @param l a <code>long</code>.
+ * @param l a {@code long}.
* @return a reference to this object.
* @throws StringIndexOutOfBoundsException if the offset is invalid.
*/
@@ -1214,20 +1226,21 @@ abstract class AbstractStringBuilder imp
}
/**
- * Inserts the string representation of the <code>float</code>
+ * Inserts the string representation of the {@code float}
* argument into this sequence.
* <p>
- * The second argument is converted to a string as if by the method
- * <code>String.valueOf</code>, and the characters of that
- * string are then inserted into this sequence at the indicated
- * offset.
- * <p>
- * The offset argument must be greater than or equal to
- * <code>0</code>, and less than or equal to the length of this
- * sequence.
+ * The overall effect is exactly as if the second argument were
+ * converted to a string by the method {@link String#valueOf(float)},
+ * and the characters of that string were then
+ * {@link #insert(int,String) inserted} into this character
+ * sequence at the indicated offset.
+ * <p>
+ * The {@code offset} argument must be greater than or equal to
+ * {@code 0}, and less than or equal to the {@linkplain #length() length}
+ * of this sequence.
*
* @param offset the offset.
- * @param f a <code>float</code>.
+ * @param f a {@code float}.
* @return a reference to this object.
* @throws StringIndexOutOfBoundsException if the offset is invalid.
*/
@@ -1236,20 +1249,21 @@ abstract class AbstractStringBuilder imp
}
/**
- * Inserts the string representation of the <code>double</code>
+ * Inserts the string representation of the {@code double}
* argument into this sequence.
* <p>
- * The second argument is converted to a string as if by the method
- * <code>String.valueOf</code>, and the characters of that
- * string are then inserted into this sequence at the indicated
- * offset.
- * <p>
- * The offset argument must be greater than or equal to
- * <code>0</code>, and less than or equal to the length of this
- * sequence.
+ * The overall effect is exactly as if the second argument were
+ * converted to a string by the method {@link String#valueOf(double)},
+ * and the characters of that string were then
+ * {@link #insert(int,String) inserted} into this character
+ * sequence at the indicated offset.
+ * <p>
+ * The {@code offset} argument must be greater than or equal to
+ * {@code 0}, and less than or equal to the {@linkplain #length() length}
+ * of this sequence.
*
* @param offset the offset.
- * @param d a <code>double</code>.
+ * @param d a {@code double}.
* @return a reference to this object.
* @throws StringIndexOutOfBoundsException if the offset is invalid.
*/
--- a/src/share/classes/java/lang/StringBuffer.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/java/lang/StringBuffer.java Mon Sep 22 22:37:31 2008 -0700
@@ -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));
--- a/src/share/classes/java/lang/StringBuilder.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/java/lang/StringBuilder.java Mon Sep 22 22:37:31 2008 -0700
@@ -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));
--- a/src/share/classes/java/lang/management/PlatformComponent.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/java/lang/management/PlatformComponent.java Mon Sep 22 22:37:31 2008 -0700
@@ -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));
--- a/src/share/classes/java/net/HttpCookie.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/java/net/HttpCookie.java Mon Sep 22 22:37:31 2008 -0700
@@ -75,6 +75,7 @@ public final class HttpCookie implements
private String path; // Path=VALUE ... URLs that see the cookie
private String portlist; // Port[="portlist"] ... the port cookie may be returned to
private boolean secure; // Secure ... e.g. use SSL
+ private boolean httpOnly; // HttpOnly ... i.e. not accessible to scripts
private int version = 1; // Version=1 ... RFC 2965 style
//
@@ -656,6 +657,32 @@ public final class HttpCookie implements
version = v;
}
+ /**
+ * Returns {@code true} if this cookie contains the <i>HttpOnly</i>
+ * attribute. This means that the cookie should not be accessible to
+ * scripting engines, like javascript.
+ *
+ * @return {@code true} if this cookie should be considered http only.
+ * @see #setHttpOnly(boolean)
+ */
+ public boolean isHttpOnly()
+ {
+ return httpOnly;
+ }
+
+ /**
+ * Indicates whether the cookie should be considered HTTP Only. If set to
+ * {@code true} it means the cookie should not be accessible to scripting
+ * engines like javascript.
+ *
+ * @param httpOnly if {@code true} make the cookie HTTP only, i.e.
+ * only visible as part of an HTTP request.
+ * @see #isHttpOnly()
+ */
+ public void setHttpOnly(boolean httpOnly)
+ {
+ this.httpOnly = httpOnly;
+ }
/**
* The utility method to check whether a host name is in a domain
@@ -877,6 +904,7 @@ public final class HttpCookie implements
|| name.equalsIgnoreCase("Port") // rfc2965 only
|| name.equalsIgnoreCase("Secure")
|| name.equalsIgnoreCase("Version")
+ || name.equalsIgnoreCase("HttpOnly")
|| name.charAt(0) == '$')
{
return true;
@@ -996,6 +1024,11 @@ public final class HttpCookie implements
cookie.setSecure(true);
}
});
+ assignors.put("httponly", new CookieAttributeAssignor(){
+ public void assign(HttpCookie cookie, String attrName, String attrValue) {
+ cookie.setHttpOnly(true);
+ }
+ });
assignors.put("version", new CookieAttributeAssignor(){
public void assign(HttpCookie cookie, String attrName, String attrValue) {
try {
--- a/src/share/classes/java/nio/ByteBufferAs-X-Buffer.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/java/nio/ByteBufferAs-X-Buffer.java Mon Sep 22 22:37:31 2008 -0700
@@ -186,7 +186,7 @@ class ByteBufferAs$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);
--- a/src/share/classes/java/nio/Direct-X-Buffer.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/java/nio/Direct-X-Buffer.java Mon Sep 22 22:37:31 2008 -0700
@@ -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);
--- a/src/share/classes/java/nio/Heap-X-Buffer.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/java/nio/Heap-X-Buffer.java Mon Sep 22 22:37:31 2008 -0700
@@ -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))
--- a/src/share/classes/java/nio/StringCharBuffer.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/java/nio/StringCharBuffer.java Mon Sep 22 22:37:31 2008 -0700
@@ -99,7 +99,7 @@ class StringCharBuffer
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,
--- a/src/share/classes/java/nio/X-Buffer.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/java/nio/X-Buffer.java Mon Sep 22 22:37:31 2008 -0700
@@ -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 ---
--- a/src/share/classes/java/security/cert/CertPathValidatorException.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/java/security/cert/CertPathValidatorException.java Mon Sep 22 22:37:31 2008 -0700
@@ -1,5 +1,5 @@
/*
- * 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.GeneralSecurityExce
* 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>
@@ -72,11 +76,16 @@ public class CertPathValidatorException
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
* @param msg the detail message
*/
public CertPathValidatorException(String msg) {
- super(msg);
+ this(msg, null);
}
/**
@@ -104,7 +113,7 @@ public class CertPathValidatorException
* 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
* 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
*/
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
(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
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
+ }
}
--- a/src/share/classes/java/util/logging/Logging.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/java/util/logging/Logging.java Mon Sep 22 22:37:31 2008 -0700
@@ -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);
}
}
--- a/src/share/classes/java/util/zip/ZipOutputStream.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/java/util/zip/ZipOutputStream.java Mon Sep 22 22:37:31 2008 -0700
@@ -1,5 +1,5 @@
/*
- * 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 DeflaterOu
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)
--- a/src/share/classes/javax/management/InstanceNotFoundException.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/javax/management/InstanceNotFoundException.java Mon Sep 22 22:37:31 2008 -0700
@@ -61,6 +61,6 @@ public class InstanceNotFoundException e
* @since 1.7
*/
public InstanceNotFoundException(ObjectName name) {
- this(name.toString());
+ this(String.valueOf(name));
}
}
--- a/src/share/classes/javax/management/MBeanServerDelegate.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/javax/management/MBeanServerDelegate.java Mon Sep 22 22:37:31 2008 -0700
@@ -304,7 +304,7 @@ public class MBeanServerDelegate impleme
* @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
--- a/src/share/classes/javax/management/ObjectName.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/javax/management/ObjectName.java Mon Sep 22 22:37:31 2008 -0700
@@ -413,7 +413,7 @@ public class ObjectName implements Compa
}
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 Compa
* 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 Compa
* @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 Compa
* 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 Compa
* @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 Compa
* 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 Compa
* 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 Compa
* @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 Compa
* @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 Compa
* 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 Compa
* 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 Compa
* 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 Compa
*
* @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 Compa
*
* @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 Compa
* @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 Compa
* @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 Compa
*
* @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 Compa
* @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();
--- a/src/share/classes/javax/management/QueryNotificationFilter.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/javax/management/QueryNotificationFilter.java Mon Sep 22 22:37:31 2008 -0700
@@ -170,7 +170,7 @@ public class QueryNotificationFilter imp
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);
--- a/src/share/classes/javax/management/event/EventClient.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/javax/management/event/EventClient.java Mon Sep 22 22:37:31 2008 -0700
@@ -264,11 +264,12 @@ public class EventClient implements Even
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;
}
};
--- a/src/share/classes/javax/management/event/EventClientDelegateMBean.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/javax/management/event/EventClientDelegateMBean.java Mon Sep 22 22:37:31 2008 -0700
@@ -96,7 +96,7 @@ public interface EventClientDelegateMBea
* <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.
--- a/src/share/classes/javax/management/event/EventSubscriber.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/javax/management/event/EventSubscriber.java Mon Sep 22 22:37:31 2008 -0700
@@ -149,10 +149,10 @@ public class EventSubscriber implements
if (listener == null)
throw new IllegalArgumentException("Null listener");
- final ListenerInfo li = new ListenerInfo(listener, filter, handback);
- List<ListenerInfo> list;
-
- Map<ObjectName, List<ListenerInfo>> map;
+ final MyListenerInfo li = new MyListenerInfo(listener, filter, handback);
+ List<MyListenerInfo> list;
+
+ Map<ObjectName, List<MyListenerInfo>> map;
Set<ObjectName> names;
if (name.isPattern()) {
map = patternSubscriptionMap;
@@ -165,7 +165,7 @@ public class EventSubscriber implements
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
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
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
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
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
}
// 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
}
};
- 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
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
// ---------------------------------
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>>();
--- a/src/share/classes/javax/management/event/FetchingEventRelay.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/javax/management/event/FetchingEventRelay.java Mon Sep 22 22:37:31 2008 -0700
@@ -31,10 +31,8 @@ import java.io.IOException;
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 implemen
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 implemen
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 implemen
new ClassLogger("javax.management.event",
"FetchingEventRelay");
private static final ThreadFactory daemonThreadFactory =
- new DaemonThreadFactory("FetchingEventRelay-executor");
+ new DaemonThreadFactory("JMX FetchingEventRelay executor %d");
}
--- a/src/share/classes/javax/management/event/RMIPushEventForwarder.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/javax/management/event/RMIPushEventForwarder.java Mon Sep 22 22:37:31 2008 -0700
@@ -185,7 +185,7 @@ public class RMIPushEventForwarder imple
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;
--- a/src/share/classes/javax/management/namespace/JMXDomain.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/javax/management/namespace/JMXDomain.java Mon Sep 22 22:37:31 2008 -0700
@@ -308,17 +308,17 @@ public class JMXDomain extends JMXNamesp
* 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);
-
- return supliedName;
+ suppliedName);
+
+ return suppliedName;
}
/**
--- a/src/share/classes/javax/management/namespace/JMXNamespace.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/javax/management/namespace/JMXNamespace.java Mon Sep 22 22:37:31 2008 -0700
@@ -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;
+ }
}
--- a/src/share/classes/javax/management/namespace/JMXNamespaces.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/javax/management/namespace/JMXNamespaces.java Mon Sep 22 22:37:31 2008 -0700
@@ -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);
}
}
--- a/src/share/classes/javax/management/namespace/JMXRemoteNamespace.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/javax/management/namespace/JMXRemoteNamespace.java Mon Sep 22 22:37:31 2008 -0700
@@ -28,13 +28,12 @@ import com.sun.jmx.defaults.JmxPropertie
import com.sun.jmx.defaults.JmxProperties;
import com.sun.jmx.mbeanserver.Util;
import com.sun.jmx.namespace.JMXNamespaceUtils;
-import com.sun.jmx.namespace.NamespaceInterceptor.DynamicProbe;
import com.sun.jmx.remote.util.EnvHelp;
import java.io.IOException;
-import java.security.AccessControlException;
import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -43,9 +42,7 @@ import javax.management.InstanceNotFound
import javax.management.InstanceNotFoundException;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanNotificationInfo;
-import javax.management.MBeanPermission;
import javax.management.MBeanServerConnection;
-import javax.management.MalformedObjectNameException;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;
import javax.management.NotificationEmitter;
@@ -117,18 +114,13 @@ public class JMXRemoteNamespace
*/
private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER;
- private static final Logger PROBE_LOG = Logger.getLogger(
- JmxProperties.NAMESPACE_LOGGER_NAME+".probe");
-
// This connection listener is used to listen for connection events from
// the underlying JMXConnector. It is used in particular to maintain the
// "connected" state in this MBean.
//
- private static class ConnectionListener implements NotificationListener {
- private final JMXRemoteNamespace handler;
- private ConnectionListener(JMXRemoteNamespace handler) {
- this.handler = handler;
+ private class ConnectionListener implements NotificationListener {
+ private ConnectionListener() {
}
public void handleNotification(Notification notification,
Object handback) {
@@ -136,7 +128,11 @@ public class JMXRemoteNamespace
return;
final JMXConnectionNotification cn =
(JMXConnectionNotification)notification;
- handler.checkState(this,cn,(JMXConnector)handback);
+ final String type = cn.getType();
+ if (JMXConnectionNotification.CLOSED.equals(type)
+ || JMXConnectionNotification.FAILED.equals(type)) {
+ checkState(this,cn,(JMXConnector)handback);
+ }
}
}
@@ -150,8 +146,7 @@ public class JMXRemoteNamespace
// because the one that is actually used is the one supplied by the
// override of getMBeanServerConnection().
private static class JMXRemoteNamespaceDelegate
- extends MBeanServerConnectionWrapper
- implements DynamicProbe {
+ extends MBeanServerConnectionWrapper {
private volatile JMXRemoteNamespace parent=null;
JMXRemoteNamespaceDelegate() {
@@ -177,9 +172,6 @@ public class JMXRemoteNamespace
}
- public boolean isProbeRequested() {
- return this.parent.isProbeRequested();
- }
}
private static final MBeanNotificationInfo connectNotification =
@@ -188,7 +180,7 @@ public class JMXRemoteNamespace
"Connected",
"Emitted when the Connected state of this object changes");
- private static long seqNumber=0;
+ private static AtomicLong seqNumber = new AtomicLong(0);
private final NotificationBroadcasterSupport broadcaster;
private final ConnectionListener listener;
@@ -198,7 +190,6 @@ public class JMXRemoteNamespace
private volatile MBeanServerConnection server = null;
private volatile JMXConnector conn = null;
private volatile ClassLoader defaultClassLoader = null;
- private volatile boolean probed;
/**
* Creates a new instance of {@code JMXRemoteNamespace}.
@@ -237,10 +228,7 @@ public class JMXRemoteNamespace
this.optionsMap = JMXNamespaceUtils.unmodifiableMap(optionsMap);
// handles (dis)connection events
- this.listener = new ConnectionListener(this);
-
- // XXX TODO: remove the probe, or simplify it.
- this.probed = false;
+ this.listener = new ConnectionListener();
}
/**
@@ -269,10 +257,6 @@ public class JMXRemoteNamespace
private Map<String,?> getEnvMap() {
return optionsMap;
- }
-
- boolean isProbeRequested() {
- return probed==false;
}
public void addNotificationListener(NotificationListener listener,
@@ -313,8 +297,8 @@ public class JMXRemoteNamespace
broadcaster.removeNotificationListener(listener, filter, handback);
}
- private static synchronized long getNextSeqNumber() {
- return seqNumber++;
+ private static long getNextSeqNumber() {
+ return seqNumber.getAndIncrement();
}
@@ -362,14 +346,18 @@ public class JMXRemoteNamespace
// lock while evaluating the true value of the connected state,
// while anyone might also call close() or connect() from a
// different thread.
- //
// The method switchConnection() (called from here too) also has the
- // same kind of complex logic.
+ // same kind of complex logic:
//
// We use the JMXConnector has a handback to the notification listener
// (emittingConnector) in order to be able to determine whether the
// notification concerns the current connector in use, or an older
- // one.
+ // one. The 'emittingConnector' is the connector from which the
+ // notification originated. This could be an 'old' connector - as
+ // closed() and connect() could already have been called before the
+ // notification arrived. So what we do is to compare the
+ // 'emittingConnector' with the current connector, to see if the
+ // notification actually comes from the curent connector.
//
boolean remove = false;
@@ -486,14 +474,12 @@ public class JMXRemoteNamespace
}
}
- private void closeall(JMXConnector... a) {
- for (JMXConnector c : a) {
- try {
- if (c != null) c.close();
- } catch (Exception x) {
- // OK: we're gonna throw the original exception later.
- LOG.finest("Ignoring exception when closing connector: "+x);
- }
+ private void close(JMXConnector c) {
+ try {
+ if (c != null) c.close();
+ } catch (Exception x) {
+ // OK: we're gonna throw the original exception later.
+ LOG.finest("Ignoring exception when closing connector: "+x);
}
}
@@ -598,26 +584,7 @@ public class JMXRemoteNamespace
}
public void connect() throws IOException {
- if (conn != null) {
- try {
- // This is much too fragile. It must go away!
- PROBE_LOG.finest("Probing again...");
- triggerProbe(getMBeanServerConnection());
- } catch(Exception x) {
- close();
- Throwable cause = x;
- // if the cause is a security exception - rethrows it...
- while (cause != null) {
- if (cause instanceof SecurityException)
- throw (SecurityException) cause;
- cause = cause.getCause();
- }
- throw new IOException("connection failed: cycle?",x);
- }
- }
LOG.fine("connecting...");
- // TODO remove these traces
- // System.err.println(getInitParameter()+" connecting");
final Map<String,Object> env =
new HashMap<String,Object>(getEnvMap());
try {
@@ -640,86 +607,16 @@ public class JMXRemoteNamespace
msc = aconn.getMBeanServerConnection();
aconn.addConnectionNotificationListener(listener,null,aconn);
} catch (IOException io) {
- closeall(aconn);
+ close(aconn);
throw io;
} catch (RuntimeException x) {
- closeall(aconn);
+ close(aconn);
throw x;
}
-
- // XXX Revisit here
- // Note from the author: This business of switching connection is
- // incredibly complex. Isn't there any means to simplify it?
- //
switchConnection(conn,aconn,msc);
- try {
- triggerProbe(msc);
- } catch(Exception x) {
- close();
- Throwable cause = x;
- // if the cause is a security exception - rethrows it...
- while (cause != null) {
- if (cause instanceof SecurityException)
- throw (SecurityException) cause;
- cause = cause.getCause();
- }
- throw new IOException("connection failed: cycle?",x);
- }
+
LOG.fine("connected.");
- }
-
- // If this is a self-linking namespace, this method should trigger
- // the emission of a probe in the wrapping NamespaceInterceptor.
- // The first call to source() in the wrapping NamespaceInterceptor
- // causes the emission of the probe.
- //
- // Note: the MBeanServer returned by getSourceServer
- // (our private JMXRemoteNamespaceDelegate inner class)
- // implements a sun private interface (DynamicProbe) which is
- // used by the NamespaceInterceptor to determine whether it should
- // send a probe or not.
- // We needed this interface here because the NamespaceInterceptor
- // has otherwise no means to knows that this object has just
- // connected, and that a new probe should be sent.
- //
- // 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 JMXNamespace (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 queryNames() it knows that it has been looping back on
- // itslef and throws an Exception - which will be raised through this
- // method, thus preventing the connection to be established...
- //
- // More info in the com.sun.jmx.namespace.NamespaceInterceptor class
- //
- // 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 void triggerProbe(final MBeanServerConnection msc)
- throws MalformedObjectNameException, IOException {
- // Query Pattern that we will send through the source server in order
- // to detect self-linking namespaces.
- //
- //
- final ObjectName pattern;
- pattern = ObjectName.getInstance("*" +
- JMXNamespaces.NAMESPACE_SEPARATOR + ":" +
- JMXNamespace.TYPE_ASSIGNMENT);
- probed = false;
- try {
- msc.queryNames(pattern, null);
- probed = true;
- } catch (AccessControlException x) {
- // if we have an MBeanPermission missing then do nothing...
- if (!(x.getPermission() instanceof MBeanPermission))
- throw x;
- PROBE_LOG.finer("Can't check for cycles: " + x);
- probed = false; // no need to do it again...
- }
}
public void close() throws IOException {
--- a/src/share/classes/javax/management/namespace/MBeanServerConnectionWrapper.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/javax/management/namespace/MBeanServerConnectionWrapper.java Mon Sep 22 22:37:31 2008 -0700
@@ -28,7 +28,6 @@ import com.sun.jmx.mbeanserver.Util;
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;
--- a/src/share/classes/javax/management/namespace/MBeanServerSupport.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/javax/management/namespace/MBeanServerSupport.java Mon Sep 22 22:37:31 2008 -0700
@@ -193,14 +193,6 @@ import javax.management.loading.ClassLoa
* }
*
* <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.ClassLoa
* 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.ClassLoa
* {@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.ClassLoa
* }
*
* 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,
--- a/src/share/classes/javax/management/remote/rmi/RMIConnector.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/javax/management/remote/rmi/RMIConnector.java Mon Sep 22 22:37:31 2008 -0700
@@ -420,7 +420,7 @@ public class RMIConnector implements JMX
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>(),
--- a/src/share/classes/sun/management/ClassLoadingImpl.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/sun/management/ClassLoadingImpl.java Mon Sep 22 22:37:31 2008 -0700
@@ -71,6 +71,6 @@ class ClassLoadingImpl implements ClassL
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);
}
}
--- a/src/share/classes/sun/management/CompilationImpl.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/sun/management/CompilationImpl.java Mon Sep 22 22:37:31 2008 -0700
@@ -70,7 +70,7 @@ class CompilationImpl implements Compila
}
public ObjectName getObjectName() {
- return Util.newObjectName(ManagementFactory.COMPILATION_MXBEAN_NAME);
+ return ObjectName.valueOf(ManagementFactory.COMPILATION_MXBEAN_NAME);
}
--- a/src/share/classes/sun/management/HotSpotDiagnostic.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/sun/management/HotSpotDiagnostic.java Mon Sep 22 22:37:31 2008 -0700
@@ -117,6 +117,6 @@ public class HotSpotDiagnostic implement
}
public ObjectName getObjectName() {
- return Util.newObjectName("com.sun.management:type=HotSpotDiagnostic");
+ return ObjectName.valueOf("com.sun.management:type=HotSpotDiagnostic");
}
}
--- a/src/share/classes/sun/management/HotspotInternal.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/sun/management/HotspotInternal.java Mon Sep 22 22:37:31 2008 -0700
@@ -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;
/**
--- a/src/share/classes/sun/management/ManagementFactoryHelper.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/sun/management/ManagementFactoryHelper.java Mon Sep 22 22:37:31 2008 -0700
@@ -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;
--- a/src/share/classes/sun/management/MemoryImpl.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/sun/management/MemoryImpl.java Mon Sep 22 22:37:31 2008 -0700
@@ -177,7 +177,7 @@ class MemoryImpl extends NotificationEmi
}
public ObjectName getObjectName() {
- return Util.newObjectName(ManagementFactory.MEMORY_MXBEAN_NAME);
+ return ObjectName.valueOf(ManagementFactory.MEMORY_MXBEAN_NAME);
}
}
--- a/src/share/classes/sun/management/OperatingSystemImpl.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/sun/management/OperatingSystemImpl.java Mon Sep 22 22:37:31 2008 -0700
@@ -74,7 +74,7 @@ public class OperatingSystemImpl impleme
}
}
public ObjectName getObjectName() {
- return Util.newObjectName(ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME);
+ return ObjectName.valueOf(ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME);
}
}
--- a/src/share/classes/sun/management/RuntimeImpl.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/sun/management/RuntimeImpl.java Mon Sep 22 22:37:31 2008 -0700
@@ -149,7 +149,7 @@ class RuntimeImpl implements RuntimeMXBe
}
public ObjectName getObjectName() {
- return Util.newObjectName(ManagementFactory.RUNTIME_MXBEAN_NAME);
+ return ObjectName.valueOf(ManagementFactory.RUNTIME_MXBEAN_NAME);
}
}
--- a/src/share/classes/sun/management/ThreadImpl.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/sun/management/ThreadImpl.java Mon Sep 22 22:37:31 2008 -0700
@@ -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);
}
}
--- a/src/share/classes/sun/management/Util.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/sun/management/Util.java Mon Sep 22 22:37:31 2008 -0700
@@ -43,12 +43,8 @@ class Util {
return (String[]) list.toArray(EMPTY_STRING_ARRAY);
}
- static ObjectName newObjectName(String name) {
- return com.sun.jmx.mbeanserver.Util.newObjectName(name);
- }
-
public static ObjectName newObjectName(String domainAndType, String name) {
- return newObjectName(domainAndType + ",name=" + name);
+ return ObjectName.valueOf(domainAndType + ",name=" + name);
}
private static ManagementPermission monitorPermission =
--- a/src/share/classes/sun/net/httpserver/ChunkedOutputStream.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/sun/net/httpserver/ChunkedOutputStream.java Mon Sep 22 22:37:31 2008 -0700
@@ -73,6 +73,7 @@ class ChunkedOutputStream extends Filter
if (count == CHUNK_SIZE) {
writeChunk();
}
+ assert count < CHUNK_SIZE;
}
public void write (byte[]b, int off, int len) throws IOException {
@@ -86,19 +87,21 @@ class ChunkedOutputStream extends Filter
writeChunk();
len -= remain;
off += remain;
- while (len > CHUNK_SIZE) {
+ while (len >= CHUNK_SIZE) {
System.arraycopy (b,off,buf,OFFSET,CHUNK_SIZE);
len -= CHUNK_SIZE;
off += CHUNK_SIZE;
count = CHUNK_SIZE;
writeChunk();
}
- pos = OFFSET;
}
if (len > 0) {
System.arraycopy (b,off,buf,pos,len);
count += len;
pos += len;
+ }
+ if (count == CHUNK_SIZE) {
+ writeChunk();
}
}
--- a/src/share/classes/sun/security/krb5/Config.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/sun/security/krb5/Config.java Mon Sep 22 22:37:31 2008 -0700
@@ -803,7 +803,7 @@ public class Config {
for (int j = 0; j < line.length(); j++) {
if (line.charAt(j) == '=') {
int index;
- key = line.substring(0, j - 1).trim();
+ key = line.substring(0, j).trim();
if (! exists(key, keyVector)) {
keyVector.addElement(key);
nameVector = new Vector<String> ();
--- a/src/share/classes/sun/security/provider/certpath/BasicChecker.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/sun/security/provider/certpath/BasicChecker.java Mon Sep 22 22:37:31 2008 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2007 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
@@ -29,12 +29,18 @@ import java.util.Collection;
import java.util.Collection;
import java.util.Date;
import java.util.Set;
+import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.PublicKey;
+import java.security.SignatureException;
import java.security.cert.Certificate;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.CertPathValidatorException;
+import java.security.cert.CertPathValidatorException.BasicReason;
import java.security.cert.X509Certificate;
import java.security.cert.PKIXCertPathChecker;
-import java.security.cert.CertPathValidatorException;
+import java.security.cert.PKIXReason;
import java.security.cert.TrustAnchor;
import java.security.interfaces.DSAParams;
import java.security.interfaces.DSAPublicKey;
@@ -152,11 +158,11 @@ class BasicChecker extends PKIXCertPathC
try {
cert.verify(prevPubKey, sigProvider);
- } catch (Exception e) {
- if (debug != null) {
- debug.println(e.getMessage());
- e.printStackTrace();
- }
+ } catch (SignatureException e) {
+ throw new CertPathValidatorException
+ (msg + " check failed", e, null, -1,
+ BasicReason.INVALID_SIGNATURE);
+ } catch (GeneralSecurityException e) {
throw new CertPathValidatorException(msg + " check failed", e);
}
@@ -176,12 +182,12 @@ class BasicChecker extends PKIXCertPathC
try {
cert.checkValidity(date);
- } catch (Exception e) {
- if (debug != null) {
- debug.println(e.getMessage());
- e.printStackTrace();
- }
- throw new CertPathValidatorException(msg + " check failed", e);
+ } catch (CertificateExpiredException e) {
+ throw new CertPathValidatorException
+ (msg + " check failed", e, null, -1, BasicReason.EXPIRED);
+ } catch (CertificateNotYetValidException e) {
+ throw new CertPathValidatorException
+ (msg + " check failed", e, null, -1, BasicReason.NOT_YET_VALID);
}
if (debug != null)
@@ -204,12 +210,16 @@ class BasicChecker extends PKIXCertPathC
// reject null or empty issuer DNs
if (X500Name.asX500Name(currIssuer).isEmpty()) {
- throw new CertPathValidatorException(msg + " check failed: " +
- "empty/null issuer DN in certificate is invalid");
+ throw new CertPathValidatorException
+ (msg + " check failed: " +
+ "empty/null issuer DN in certificate is invalid", null,
+ null, -1, PKIXReason.NAME_CHAINING);
}
if (!(currIssuer.equals(prevSubject))) {
- throw new CertPathValidatorException(msg + " check failed");
+ throw new CertPathValidatorException
+ (msg + " check failed", null, null, -1,
+ PKIXReason.NAME_CHAINING);
}
if (debug != null)
@@ -270,7 +280,7 @@ class BasicChecker extends PKIXCertPathC
params.getQ(),
params.getG());
usableKey = kf.generatePublic(ks);
- } catch (Exception e) {
+ } catch (GeneralSecurityException e) {
throw new CertPathValidatorException("Unable to generate key with" +
" inherited parameters: " +
e.getMessage(), e);
--- a/src/share/classes/sun/security/provider/certpath/ConstraintsChecker.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/sun/security/provider/certpath/ConstraintsChecker.java Mon Sep 22 22:37:31 2008 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2006 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
@@ -32,9 +32,10 @@ import java.io.IOException;
import java.io.IOException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
+import java.security.cert.CertPathValidatorException;
import java.security.cert.X509Certificate;
import java.security.cert.PKIXCertPathChecker;
-import java.security.cert.CertPathValidatorException;
+import java.security.cert.PKIXReason;
import sun.security.util.Debug;
import sun.security.x509.PKIXExtensions;
import sun.security.x509.NameConstraintsExtension;
@@ -147,7 +148,8 @@ class ConstraintsChecker extends PKIXCer
try {
if (!prevNC.verify(currCert)) {
- throw new CertPathValidatorException(msg + " check failed");
+ throw new CertPathValidatorException(msg + " check failed",
+ null, null, -1, PKIXReason.INVALID_NAME);
}
} catch (IOException ioe) {
throw new CertPathValidatorException(ioe);
@@ -228,8 +230,9 @@ class ConstraintsChecker extends PKIXCer
if (i < certPathLength) {
int pathLenConstraint = currCert.getBasicConstraints();
if (pathLenConstraint == -1) {
- throw new CertPathValidatorException(msg + " check failed: "
- + "this is not a CA certificate");
+ throw new CertPathValidatorException
+ (msg + " check failed: this is not a CA certificate", null,
+ null, -1, PKIXReason.NOT_CA_CERT);
}
if (!X509CertImpl.isSelfIssued(currCert)) {
@@ -237,7 +240,8 @@ class ConstraintsChecker extends PKIXCer
throw new CertPathValidatorException
(msg + " check failed: pathLenConstraint violated - "
+ "this cert must be the last cert in the "
- + "certification path");
+ + "certification path", null, null, -1,
+ PKIXReason.PATH_TOO_LONG);
}
maxPathLength--;
}
--- a/src/share/classes/sun/security/provider/certpath/CrlRevocationChecker.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/sun/security/provider/certpath/CrlRevocationChecker.java Mon Sep 22 22:37:31 2008 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2007 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
@@ -39,6 +39,7 @@ import java.security.NoSuchAlgorithmExce
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.cert.*;
+import java.security.cert.CertPathValidatorException.BasicReason;
import java.security.interfaces.DSAPublicKey;
import javax.security.auth.x500.X500Principal;
import sun.security.util.Debug;
@@ -268,7 +269,8 @@ class CrlRevocationChecker extends PKIXC
" circular dependency");
}
throw new CertPathValidatorException
- ("Could not determine revocation status");
+ ("Could not determine revocation status", null, null, -1,
+ BasicReason.UNDETERMINED_REVOCATION_STATUS);
}
// init the state for this run
@@ -324,7 +326,8 @@ class CrlRevocationChecker extends PKIXC
return;
} else {
throw new CertPathValidatorException
- ("Could not determine revocation status");
+ ("Could not determine revocation status", null, null, -1,
+ BasicReason.UNDETERMINED_REVOCATION_STATUS);
}
}
@@ -370,7 +373,8 @@ class CrlRevocationChecker extends PKIXC
+ unresCritExts);
}
throw new CertPathValidatorException
- ("Could not determine revocation status");
+ ("Could not determine revocation status", null, null,
+ -1, BasicReason.UNDETERMINED_REVOCATION_STATUS);
}
}
@@ -378,10 +382,11 @@ class CrlRevocationChecker extends PKIXC
if (reasonCode == null) {
reasonCode = CRLReason.UNSPECIFIED;
}
- throw new CertPathValidatorException(
- new CertificateRevokedException
- (entry.getRevocationDate(), reasonCode,
- crl.getIssuerX500Principal(), entry.getExtensions()));
+ Throwable t = new CertificateRevokedException
+ (entry.getRevocationDate(), reasonCode,
+ crl.getIssuerX500Principal(), entry.getExtensions());
+ throw new CertPathValidatorException(t.getMessage(), t,
+ null, -1, BasicReason.REVOKED);
}
}
}
@@ -428,7 +433,8 @@ class CrlRevocationChecker extends PKIXC
" circular dependency");
}
throw new CertPathValidatorException
- ("Could not determine revocation status");
+ ("Could not determine revocation status", null, null,
+ -1, BasicReason.UNDETERMINED_REVOCATION_STATUS);
}
// If prevKey wasn't trusted, maybe we just didn't have the right
@@ -617,7 +623,7 @@ class CrlRevocationChecker extends PKIXC
return;
} catch (CertPathValidatorException cpve) {
// If it is revoked, rethrow exception
- if (cpve.getCause() instanceof CertificateRevokedException) {
+ if (cpve.getReason() == BasicReason.REVOKED) {
throw cpve;
}
// Otherwise, ignore the exception and
@@ -628,7 +634,8 @@ class CrlRevocationChecker extends PKIXC
throw new CertPathValidatorException(iape);
} catch (CertPathBuilderException cpbe) {
throw new CertPathValidatorException
- ("Could not determine revocation status", cpbe);
+ ("Could not determine revocation status", null, null,
+ -1, BasicReason.UNDETERMINED_REVOCATION_STATUS);
}
}
}
--- a/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java Mon Sep 22 22:37:31 2008 -0700
@@ -32,6 +32,7 @@ import java.security.InvalidKeyException
import java.security.InvalidKeyException;
import java.security.cert.CertificateException;
import java.security.cert.CertPathValidatorException;
+import java.security.cert.PKIXReason;
import java.security.cert.CertStore;
import java.security.cert.CertStoreException;
import java.security.cert.PKIXBuilderParameters;
@@ -732,8 +733,9 @@ class ForwardBuilder extends Builder {
PKIXExtensions.ExtendedKeyUsage_Id.toString());
if (!unresCritExts.isEmpty())
- throw new CertificateException("Unrecognized critical "
- + "extension(s)");
+ throw new CertPathValidatorException
+ ("Unrecognized critical extension(s)", null, null, -1,
+ PKIXReason.UNRECOGNIZED_CRIT_EXT);
}
}
--- a/src/share/classes/sun/security/provider/certpath/KeyChecker.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/sun/security/provider/certpath/KeyChecker.java Mon Sep 22 22:37:31 2008 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2003 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
@@ -27,6 +27,7 @@ package sun.security.provider.certpath;
import java.util.*;
import java.security.cert.*;
+import java.security.cert.PKIXReason;
import sun.security.util.Debug;
import sun.security.x509.PKIXExtensions;
@@ -75,11 +76,12 @@ class KeyChecker extends PKIXCertPathChe
if (!forward) {
remainingCerts = certPathLen;
} else {
- throw new CertPathValidatorException("forward checking not supported");
+ throw new CertPathValidatorException
+ ("forward checking not supported");
}
}
- public boolean isForwardCheckingSupported() {
+ public final boolean isForwardCheckingSupported() {
return false;
}
@@ -155,8 +157,9 @@ class KeyChecker extends PKIXCertPathChe
// throw an exception if the keyCertSign bit is not set
if (!keyUsageBits[keyCertSign]) {
- throw new CertPathValidatorException(msg + " check failed: "
- + "keyCertSign bit is not set");
+ throw new CertPathValidatorException
+ (msg + " check failed: keyCertSign bit is not set", null,
+ null, -1, PKIXReason.INVALID_KEY_USAGE);
}
if (debug != null) {
--- a/src/share/classes/sun/security/provider/certpath/OCSPChecker.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/sun/security/provider/certpath/OCSPChecker.java Mon Sep 22 22:37:31 2008 -0700
@@ -33,6 +33,7 @@ import java.security.PrivilegedAction;
import java.security.PrivilegedAction;
import java.security.Security;
import java.security.cert.*;
+import java.security.cert.CertPathValidatorException.BasicReason;
import java.net.*;
import javax.security.auth.x500.X500Principal;
@@ -381,17 +382,18 @@ class OCSPChecker extends PKIXCertPathCh
}
if (certOCSPStatus == OCSPResponse.CERT_STATUS_REVOKED) {
- throw new CertPathValidatorException(
- new CertificateRevokedException(
+ Throwable t = new CertificateRevokedException(
ocspResponse.getRevocationTime(),
ocspResponse.getRevocationReason(),
responderCert.getSubjectX500Principal(),
- ocspResponse.getSingleExtensions()));
+ ocspResponse.getSingleExtensions());
+ throw new CertPathValidatorException(t.getMessage(), t,
+ null, -1, BasicReason.REVOKED);
} else if (certOCSPStatus == OCSPResponse.CERT_STATUS_UNKNOWN) {
throw new CertPathValidatorException(
"Certificate's revocation status is unknown", null, cp,
- remainingCerts);
+ remainingCerts, BasicReason.UNDETERMINED_REVOCATION_STATUS);
}
} catch (Exception e) {
throw new CertPathValidatorException(e);
--- a/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java Mon Sep 22 22:37:31 2008 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2007 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
@@ -38,6 +38,7 @@ import java.security.cert.PKIXCertPathCh
import java.security.cert.PKIXCertPathChecker;
import java.security.cert.PKIXCertPathValidatorResult;
import java.security.cert.PKIXParameters;
+import java.security.cert.PKIXReason;
import java.security.cert.PolicyNode;
import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate;
@@ -47,7 +48,6 @@ import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Date;
import java.util.Set;
-import java.util.HashSet;
import javax.security.auth.x500.X500Principal;
import sun.security.util.Debug;
@@ -67,6 +67,7 @@ public class PKIXCertPathValidator exten
private List<PKIXCertPathChecker> userCheckers;
private String sigProvider;
private BasicChecker basicChecker;
+ private String ocspProperty;
/**
* Default constructor.
@@ -126,7 +127,7 @@ public class PKIXCertPathValidator exten
// Must copy elements of certList into a new modifiable List before
// calling Collections.reverse().
- List<X509Certificate> certList = new ArrayList<X509Certificate>
+ ArrayList<X509Certificate> certList = new ArrayList<X509Certificate>
((List<X509Certificate>)cp.getCertificates());
if (debug != null) {
if (certList.isEmpty()) {
@@ -201,7 +202,8 @@ public class PKIXCertPathValidator exten
}
// (b) otherwise, generate new exception
throw new CertPathValidatorException
- ("Path does not chain with any of the trust anchors");
+ ("Path does not chain with any of the trust anchors",
+ null, null, -1, PKIXReason.NO_TRUST_ANCHOR);
}
/**
@@ -210,7 +212,6 @@ public class PKIXCertPathValidator exten
*/
private boolean isWorthTrying(X509Certificate trustedCert,
X509Certificate firstCert)
- throws CertPathValidatorException
{
if (debug != null) {
debug.println("PKIXCertPathValidator.isWorthTrying() checking "
@@ -240,7 +241,6 @@ public class PKIXCertPathValidator exten
* Internal method to setup the internal state
*/
private void populateVariables(PKIXParameters pkixParam)
- throws CertPathValidatorException
{
// default value for testDate is current time
testDate = pkixParam.getDate();
@@ -250,6 +250,17 @@ public class PKIXCertPathValidator exten
userCheckers = pkixParam.getCertPathCheckers();
sigProvider = pkixParam.getSigProvider();
+
+ if (pkixParam.isRevocationEnabled()) {
+ // Examine OCSP security property
+ ocspProperty = AccessController.doPrivileged(
+ new PrivilegedAction<String>() {
+ public String run() {
+ return
+ Security.getProperty(OCSPChecker.OCSP_ENABLE_PROP);
+ }
+ });
+ }
}
/**
@@ -259,12 +270,9 @@ public class PKIXCertPathValidator exten
*/
private PolicyNode doValidate(
TrustAnchor anchor, CertPath cpOriginal,
- List<X509Certificate> certList, PKIXParameters pkixParam,
+ ArrayList<X509Certificate> certList, PKIXParameters pkixParam,
PolicyNodeImpl rootNode) throws CertPathValidatorException
{
- List<PKIXCertPathChecker> certPathCheckers =
- new ArrayList<PKIXCertPathChecker>();
-
int certPathLen = certList.size();
basicChecker = new BasicChecker(anchor, testDate, sigProvider, false);
@@ -281,6 +289,8 @@ public class PKIXCertPathValidator exten
pkixParam.getPolicyQualifiersRejected(),
rootNode);
+ ArrayList<PKIXCertPathChecker> certPathCheckers =
+ new ArrayList<PKIXCertPathChecker>();
// add standard checkers that we will be using
certPathCheckers.add(keyChecker);
certPathCheckers.add(constraintsChecker);
@@ -290,15 +300,6 @@ public class PKIXCertPathValidator exten
// only add a revocationChecker if revocation is enabled
if (pkixParam.isRevocationEnabled()) {
- // Examine OCSP security property
- String ocspProperty = AccessController.doPrivileged(
- new PrivilegedAction<String>() {
- public String run() {
- return
- Security.getProperty(OCSPChecker.OCSP_ENABLE_PROP);
- }
- });
-
// Use OCSP if it has been enabled
if ("true".equalsIgnoreCase(ocspProperty)) {
OCSPChecker ocspChecker =
--- a/src/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java Mon Sep 22 22:37:31 2008 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2006 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
@@ -30,11 +30,12 @@ import java.util.Collections;
import java.util.Collections;
import java.util.List;
import java.util.Set;
-import java.util.Iterator;
+import java.security.cert.CertificateRevokedException;
import java.security.cert.CertPath;
import java.security.cert.CertPathValidatorException;
-import java.security.cert.CertificateRevokedException;
+import java.security.cert.CertPathValidatorException.BasicReason;
import java.security.cert.PKIXCertPathChecker;
+import java.security.cert.PKIXReason;
import java.security.cert.X509Certificate;
/**
@@ -153,10 +154,11 @@ class PKIXMasterCertPathValidator {
*/
CertPathValidatorException currentCause =
new CertPathValidatorException(cpve.getMessage(),
- cpve.getCause(), cpOriginal, cpSize - (i + 1));
+ cpve.getCause(), cpOriginal, cpSize - (i + 1),
+ cpve.getReason());
// Check if OCSP has confirmed that the cert was revoked
- if (cpve.getCause() instanceof CertificateRevokedException) {
+ if (cpve.getReason() == BasicReason.REVOKED) {
throw currentCause;
}
// Check if it is appropriate to failover
@@ -184,7 +186,8 @@ class PKIXMasterCertPathValidator {
debug.println("checking for unresolvedCritExts");
if (!unresolvedCritExts.isEmpty()) {
throw new CertPathValidatorException("unrecognized " +
- "critical extension(s)", null, cpOriginal, cpSize-(i+1));
+ "critical extension(s)", null, cpOriginal, cpSize-(i+1),
+ PKIXReason.UNRECOGNIZED_CRIT_EXT);
}
if (debug != null)
--- a/src/share/classes/sun/security/provider/certpath/PolicyChecker.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/sun/security/provider/certpath/PolicyChecker.java Mon Sep 22 22:37:31 2008 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2006 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
@@ -30,11 +30,12 @@ import java.io.IOException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
+import java.security.cert.CertPathValidatorException;
import java.security.cert.PKIXCertPathChecker;
-import java.security.cert.CertPathValidatorException;
+import java.security.cert.PKIXReason;
import java.security.cert.PolicyNode;
import java.security.cert.PolicyQualifierInfo;
+import java.security.cert.X509Certificate;
import sun.security.util.Debug;
import sun.security.x509.CertificatePoliciesExtension;
@@ -482,8 +483,9 @@ class PolicyChecker extends PKIXCertPath
// the policyQualifiersRejected flag is set in the params
if (!pQuals.isEmpty() && rejectPolicyQualifiers &&
policiesCritical) {
- throw new CertPathValidatorException("critical " +
- "policy qualifiers present in certificate");
+ throw new CertPathValidatorException(
+ "critical policy qualifiers present in certificate",
+ null, null, -1, PKIXReason.INVALID_POLICY);
}
// PKIX: Section 6.1.3: Step (d)(1)(i)
@@ -567,7 +569,8 @@ class PolicyChecker extends PKIXCertPath
if ((explicitPolicy == 0) && (rootNode == null)) {
throw new CertPathValidatorException
- ("non-null policy tree required and policy tree is null");
+ ("non-null policy tree required and policy tree is null",
+ null, null, -1, PKIXReason.INVALID_POLICY);
}
return rootNode;
@@ -776,12 +779,14 @@ class PolicyChecker extends PKIXCertPath
if (issuerDomain.equals(ANY_POLICY)) {
throw new CertPathValidatorException
- ("encountered an issuerDomainPolicy of ANY_POLICY");
+ ("encountered an issuerDomainPolicy of ANY_POLICY",
+ null, null, -1, PKIXReason.INVALID_POLICY);
}
if (subjectDomain.equals(ANY_POLICY)) {
throw new CertPathValidatorException
- ("encountered a subjectDomainPolicy of ANY_POLICY");
+ ("encountered a subjectDomainPolicy of ANY_POLICY",
+ null, null, -1, PKIXReason.INVALID_POLICY);
}
Set<PolicyNodeImpl> validNodes =
--- a/src/share/classes/sun/security/provider/certpath/ReverseBuilder.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/sun/security/provider/certpath/ReverseBuilder.java Mon Sep 22 22:37:31 2008 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2006 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
@@ -29,14 +29,15 @@ import java.security.GeneralSecurityExce
import java.security.GeneralSecurityException;
import java.security.Principal;
import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
import java.security.cert.CertPathValidatorException;
import java.security.cert.CertStore;
import java.security.cert.CertStoreException;
import java.security.cert.PKIXBuilderParameters;
import java.security.cert.PKIXCertPathChecker;
import java.security.cert.PKIXParameters;
+import java.security.cert.PKIXReason;
import java.security.cert.TrustAnchor;
+import java.security.cert.X509Certificate;
import java.security.cert.X509CertSelector;
import java.util.ArrayList;
import java.util.Collection;
@@ -402,7 +403,8 @@ class ReverseBuilder extends Builder {
*/
if ((currentState.remainingCACerts <= 0) && !X509CertImpl.isSelfIssued(cert)) {
throw new CertPathValidatorException
- ("pathLenConstraint violated, path too long");
+ ("pathLenConstraint violated, path too long", null,
+ null, -1, PKIXReason.PATH_TOO_LONG);
}
/*
@@ -438,7 +440,8 @@ class ReverseBuilder extends Builder {
try {
if (!currentState.nc.verify(cert)){
throw new CertPathValidatorException
- ("name constraints check failed");
+ ("name constraints check failed", null, null, -1,
+ PKIXReason.INVALID_NAME);
}
} catch (IOException ioe){
throw new CertPathValidatorException(ioe);
@@ -483,7 +486,9 @@ class ReverseBuilder extends Builder {
unresolvedCritExts.remove(PKIXExtensions.ExtendedKeyUsage_Id.toString());
if (!unresolvedCritExts.isEmpty())
- throw new CertificateException("Unrecognized critical extension(s)");
+ throw new CertPathValidatorException
+ ("Unrecognized critical extension(s)", null, null, -1,
+ PKIXReason.UNRECOGNIZED_CRIT_EXT);
}
/*
--- a/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java Mon Sep 22 22:37:31 2008 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2007 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
@@ -30,6 +30,9 @@ import java.security.InvalidAlgorithmPar
import java.security.InvalidAlgorithmParameterException;
import java.security.Principal;
import java.security.PublicKey;
+import java.security.cert.*;
+import java.security.cert.PKIXReason;
+import java.security.interfaces.DSAPublicKey;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -39,10 +42,6 @@ import java.util.List;
import java.util.List;
import java.util.LinkedList;
import java.util.Set;
-
-import java.security.cert.*;
-import java.security.interfaces.DSAPublicKey;
-
import javax.security.auth.x500.X500Principal;
import sun.security.x509.X500Name;
@@ -565,8 +564,9 @@ public final class SunCertPathBuilder ex
(PKIXExtensions.ExtendedKeyUsage_Id.toString());
if (!unresCritExts.isEmpty()) {
- throw new CertPathValidatorException("unrecognized "
- + "critical extension(s)");
+ throw new CertPathValidatorException
+ ("unrecognized critical extension(s)", null,
+ null, -1, PKIXReason.UNRECOGNIZED_CRIT_EXT);
}
}
}
--- a/src/share/classes/sun/tools/jconsole/Plotter.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/sun/tools/jconsole/Plotter.java Mon Sep 22 22:37:31 2008 -0700
@@ -30,18 +30,15 @@ import java.beans.*;
import java.beans.*;
import java.io.*;
import java.lang.reflect.Array;
-import java.text.*;
import java.util.*;
import javax.accessibility.*;
import javax.swing.*;
import javax.swing.border.*;
-import javax.swing.event.*;
import javax.swing.filechooser.*;
import javax.swing.filechooser.FileFilter;
import com.sun.tools.jconsole.JConsoleContext;
-import com.sun.tools.jconsole.JConsoleContext.ConnectionState;
import static com.sun.tools.jconsole.JConsoleContext.ConnectionState.*;
@@ -130,6 +127,7 @@ public class Plotter extends JComponent
private int bottomMargin = 45;
private int leftMargin = 65;
private int rightMargin = 70;
+ private final boolean displayLegend;
public Plotter() {
this(Unit.NONE, 0);
@@ -139,15 +137,21 @@ public class Plotter extends JComponent
this(unit, 0);
}
+ public Plotter(Unit unit, int decimals) {
+ this(unit,decimals,true);
+ }
+
// Note: If decimals > 0 then values must be decimally shifted left
// that many places, i.e. multiplied by Math.pow(10.0, decimals).
- public Plotter(Unit unit, int decimals) {
+ public Plotter(Unit unit, int decimals, boolean displayLegend) {
+ this.displayLegend = displayLegend;
setUnit(unit);
setDecimals(decimals);
enableEvents(AWTEvent.MOUSE_EVENT_MASK);
addMouseListener(new MouseAdapter() {
+ @Override
public void mousePressed(MouseEvent e) {
if (getParent() instanceof PlotterPanel) {
getParent().requestFocusInWindow();
@@ -240,6 +244,7 @@ public class Plotter extends JComponent
}
}
+ @Override
public JPopupMenu getComponentPopupMenu() {
if (popupMenu == null) {
popupMenu = new JPopupMenu(Resources.getText("Chart:"));
@@ -330,6 +335,7 @@ public class Plotter extends JComponent
}
}
+ @Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
@@ -670,7 +676,7 @@ public class Plotter extends JComponent
curValue += "%";
}
int valWidth = fm.stringWidth(curValue);
- String legend = seq.name;
+ String legend = (displayLegend?seq.name:"");
int legendWidth = fm.stringWidth(legend);
if (checkRightMargin(valWidth) || checkRightMargin(legendWidth)) {
// Wait for next repaint
@@ -986,10 +992,12 @@ public class Plotter extends JComponent
}
private static class SaveDataFileChooser extends JFileChooser {
+ private static final long serialVersionUID = -5182890922369369669L;
SaveDataFileChooser() {
setFileFilter(new FileNameExtensionFilter("CSV file", "csv"));
}
+ @Override
public void approveSelection() {
File file = getSelectedFile();
if (file != null) {
@@ -1034,6 +1042,7 @@ public class Plotter extends JComponent
}
}
+ @Override
public AccessibleContext getAccessibleContext() {
if (accessibleContext == null) {
accessibleContext = new AccessiblePlotter();
@@ -1042,10 +1051,12 @@ public class Plotter extends JComponent
}
protected class AccessiblePlotter extends AccessibleJComponent {
+ private static final long serialVersionUID = -3847205410473510922L;
protected AccessiblePlotter() {
setAccessibleName(getText("Plotter.accessibleName"));
}
+ @Override
public String getAccessibleName() {
String name = super.getAccessibleName();
@@ -1076,6 +1087,7 @@ public class Plotter extends JComponent
return name;
}
+ @Override
public AccessibleRole getAccessibleRole() {
return AccessibleRole.CANVAS;
}
--- a/src/share/classes/sun/tools/jconsole/inspector/XMBeanAttributes.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/sun/tools/jconsole/inspector/XMBeanAttributes.java Mon Sep 22 22:37:31 2008 -0700
@@ -872,8 +872,8 @@ public class XMBeanAttributes extends XT
MaximizedCellRenderer(Component comp) {
this.comp = comp;
Dimension d = comp.getPreferredSize();
- if (d.getHeight() > 200) {
- comp.setPreferredSize(new Dimension((int) d.getWidth(), 200));
+ if (d.getHeight() > 220) {
+ comp.setPreferredSize(new Dimension((int) d.getWidth(), 220));
}
}
@Override
--- a/src/share/classes/sun/tools/jconsole/inspector/XPlotter.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/sun/tools/jconsole/inspector/XPlotter.java Mon Sep 22 22:37:31 2008 -0700
@@ -34,7 +34,7 @@ public class XPlotter extends Plotter {
JTable table;
public XPlotter(JTable table,
Plotter.Unit unit) {
- super(unit);
+ super(unit,0,false);
this.table = table;
}
@Override
--- a/src/share/classes/sun/tools/jconsole/inspector/XPlottingViewer.java Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/classes/sun/tools/jconsole/inspector/XPlottingViewer.java Mon Sep 22 22:37:31 2008 -0700
@@ -27,14 +27,10 @@ package sun.tools.jconsole.inspector;
import java.awt.*;
import java.awt.event.*;
-import java.io.*;
import java.util.*;
import java.util.Timer;
-import javax.management.*;
import javax.swing.*;
-import javax.swing.border.*;
-import javax.swing.event.*;
import sun.tools.jconsole.*;
@@ -127,6 +123,7 @@ public class XPlottingViewer extends Plo
setBackground(g.getColor());
plotter.paintComponent(g);
}*/
+ @Override
public void actionPerformed(ActionEvent evt) {
plotterCache.remove(key);
Timer t = timerCache.remove(key);
@@ -141,9 +138,11 @@ public class XPlottingViewer extends Plo
JTable table) {
final Plotter plotter = new XPlotter(table, Plotter.Unit.NONE) {
Dimension prefSize = new Dimension(400, 170);
+ @Override
public Dimension getPreferredSize() {
return prefSize;
}
+ @Override
public Dimension getMinimumSize() {
return prefSize;
}
@@ -183,42 +182,40 @@ public class XPlottingViewer extends Plo
return plotter;
}
- //Create Plotter display
private void setupDisplay(Plotter plotter) {
- //setLayout(new GridLayout(2,0));
- GridBagLayout gbl = new GridBagLayout();
- setLayout(gbl);
+ final JPanel buttonPanel = new JPanel();
+ final GridBagLayout gbl = new GridBagLayout();
+ buttonPanel.setLayout(gbl);
+ setLayout(new BorderLayout());
plotButton = new JButton(Resources.getText("Discard chart"));
plotButton.addActionListener(this);
plotButton.setEnabled(true);
- // Add the display to the top four cells
GridBagConstraints buttonConstraints = new GridBagConstraints();
buttonConstraints.gridx = 0;
buttonConstraints.gridy = 0;
buttonConstraints.fill = GridBagConstraints.VERTICAL;
buttonConstraints.anchor = GridBagConstraints.CENTER;
gbl.setConstraints(plotButton, buttonConstraints);
- add(plotButton);
-
- GridBagConstraints plotterConstraints = new GridBagConstraints();
- plotterConstraints.gridx = 0;
- plotterConstraints.gridy = 1;
- plotterConstraints.weightx = 1;
- //plotterConstraints.gridwidth = (int) plotter.getPreferredSize().getWidth();
- //plotterConstraints.gridheight = (int) plotter.getPreferredSize().getHeight();
- plotterConstraints.fill = GridBagConstraints.VERTICAL;
- gbl.setConstraints(plotter, plotterConstraints);
-
-
- //bordered = new JPanel();
- //bordered.setPreferredSize(new Dimension(400, 250));
- //bordered.add(plotButton);
- //bordered.add(plotter);
-
- //add(bordered);
-
+ buttonPanel.add(plotButton);
+
+ if (attributeName != null && attributeName.length()!=0) {
+ final JPanel plotterLabelPanel = new JPanel();
+ final JLabel label = new JLabel(attributeName);
+ final GridBagLayout gbl2 = new GridBagLayout();
+ plotterLabelPanel.setLayout(gbl2);
+ final GridBagConstraints labelConstraints = new GridBagConstraints();
+ labelConstraints.gridx = 0;
+ labelConstraints.gridy = 0;
+ labelConstraints.fill = GridBagConstraints.VERTICAL;
+ labelConstraints.anchor = GridBagConstraints.CENTER;
+ labelConstraints.ipady = 10;
+ gbl2.setConstraints(label, labelConstraints);
+ plotterLabelPanel.add(label);
+ add(plotterLabelPanel, BorderLayout.NORTH);
+ }
setPlotter(plotter);
+ add(buttonPanel, BorderLayout.SOUTH);
repaint();
}
--- a/src/share/native/java/util/zip/zip_util.c Fri Sep 19 19:38:12 2008 -0700
+++ b/src/share/native/java/util/zip/zip_util.c Mon Sep 22 22:37:31 2008 -0700
@@ -1,5 +1,5 @@
/*
- * 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
@@ -722,16 +722,22 @@ ZIP_Put_In_Cache(const char *name, ZFILE
}
len = zip->len = ZFILE_Lseek(zfd, 0, SEEK_END);
- if (len == -1) {
- if (pmsg && JVM_GetLastErrorString(errbuf, sizeof(errbuf)) > 0)
- *pmsg = errbuf;
+ if (len <= 0) {
+ if (len == 0) { /* zip file is empty */
+ if (pmsg) {
+ *pmsg = "zip file is empty";
+ }
+ } else { /* error */
+ if (pmsg && JVM_GetLastErrorString(errbuf, sizeof(errbuf)) > 0)
+ *pmsg = errbuf;
+ }
ZFILE_Close(zfd);
freeZip(zip);
return NULL;
}
zip->zfd = zfd;
- if (readCEN(zip, -1) <= 0) {
+ if (readCEN(zip, -1) < 0) {
/* An error occurred while trying to read the zip file */
if (pmsg != 0) {
/* Set the zip error message */
@@ -947,10 +953,15 @@ ZIP_GetEntry(jzfile *zip, char *name, ji
ZIP_GetEntry(jzfile *zip, char *name, jint ulen)
{
unsigned int hsh = hash(name);
- jint idx = zip->table[hsh % zip->tablelen];
- jzentry *ze;
+ jint idx;
+ jzentry *ze = 0;
ZIP_Lock(zip);
+ if (zip->total == 0) {
+ goto Finally;
+ }
+
+ idx = zip->table[hsh % zip->tablelen];
/*
* This while loop is an optimization where a double lookup
@@ -1025,6 +1036,7 @@ ZIP_GetEntry(jzfile *zip, char *name, ji
ulen = 0;
}
+Finally:
ZIP_Unlock(zip);
return ze;
}
--- a/test/com/sun/jdi/ClassesByName2Test.java Fri Sep 19 19:38:12 2008 -0700
+++ b/test/com/sun/jdi/ClassesByName2Test.java Mon Sep 22 22:37:31 2008 -0700
@@ -41,8 +41,7 @@ import java.util.*;
/********** target program **********/
class ClassesByName2Targ {
- public static void ready() {
- System.out.println("Ready!");
+ static void bkpt() {
}
public static void main(String[] args){
@@ -74,22 +73,24 @@ class ClassesByName2Targ {
}
};
- ready();
-
two.start();
one.start();
zero.start();
try {
zero.join();
+ System.out.println("zero joined");
one.join();
+ System.out.println("one joined");
two.join();
+ System.out.println("two joined");
} catch (InterruptedException iex) {
iex.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
+ bkpt();
System.out.println("Goodbye from ClassesByName2Targ!");
}
}
@@ -97,29 +98,64 @@ class ClassesByName2Targ {
/********** test program **********/
public class ClassesByName2Test extends TestScaffold {
+ volatile boolean stop = false;
ClassesByName2Test (String args[]) {
super(args);
+ }
+
+ public void breakpointReached(BreakpointEvent event) {
+ System.out.println("Got BreakpointEvent: " + event);
+ stop = true;
+ }
+
+ public void eventSetComplete(EventSet set) {
+ // Don't resume.
}
public static void main(String[] args) throws Exception {
new ClassesByName2Test(args).startTests();
}
+ void breakpointAtMethod(ReferenceType ref, String methodName)
+ throws Exception {
+ List meths = ref.methodsByName(methodName);
+ if (meths.size() != 1) {
+ throw new Exception("test error: should be one " +
+ methodName);
+ }
+ Method meth = (Method)meths.get(0);
+ BreakpointRequest bkptReq = vm().eventRequestManager().
+ createBreakpointRequest(meth.location());
+ bkptReq.enable();
+ try {
+ addListener (this);
+ } catch (Exception ex){
+ ex.printStackTrace();
+ failure("failure: Could not add listener");
+ throw new Exception("ClassesByname2Test: failed");
+ }
+ }
+
protected void runTests() throws Exception {
+ BreakpointEvent bpe = startToMain("ClassesByName2Targ");
+
/*