--- a/.hgtags Tue Nov 11 08:59:43 2008 +0000
+++ b/.hgtags Tue Nov 11 09:07:58 2008 +0000
@@ -12,3 +12,4 @@ cf4894b78ceb966326e93bf221db0c2d14d59218
cf4894b78ceb966326e93bf221db0c2d14d59218 jdk7-b35
134fd1a656ea85acd1f97f6700f75029b9b472a0 jdk7-b36
14f50aee4989b75934d385c56a83da0c23d2f68b jdk7-b37
+cc5f810b5af8a3a83b0df5a29d9e24d7a0ff8086 jdk7-b38
--- a/make/netbeans/jmx/build.xml Tue Nov 11 08:59:43 2008 +0000
+++ b/make/netbeans/jmx/build.xml Tue Nov 11 09:07:58 2008 +0000
@@ -44,13 +44,13 @@
<!-- because they depend on the values of BUILD_DATE and BUILD_DATE_SIMPLE -->
<!-- At this time, ./build.properties has not been loaded yet. -->
<property name="project.build.name" value="openjdk-bXX"/>
- <property name="project.build.fulltag"
+ <property name="project.build.fulltag"
value="${ant.project.name}-${project.build.name}-${BUILD_DATE}" />
<!-- unchecked warnings will be fixed in JMX 2.0 as part of the work
being done on JSR 255 new features -->
- <property name="javac.options"
- value="-Xlint -Xlint:-unchecked -Xlint:-deprecation"/>
+ <property name="javac.options"
+ value="-Xlint -Xlint:-deprecation"/>
</target>
@@ -58,13 +58,13 @@
<!-- Dir to keep generated stub source -->
<mkdir dir="${gensrc.dir}" />
</target>
-
+
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- Call rmic-jmx subtargets -->
<target name="-rmic-jmx" depends="-init,-rmic-jmx-jrmp,-rmic-jmx-iiop"
- description="Calls -init,-rmic-jmx-jrmp,-rmic-jmx-iiop"
+ description="Calls -init,-rmic-jmx-jrmp,-rmic-jmx-iiop"
/>
@@ -96,7 +96,7 @@
<target name="-rmic-jmx-iiop" depends="-init,-check-jmx-iiop-uptodate" unless="jmx-iiop-uptodate"
description="Generate RMI IIOP stub class files for remote objects. Do not keep generated java files." >
-
+
<rmic base="${classes.dir}"
includeAntRuntime="no"
includeJavaRuntime="no"
@@ -115,11 +115,11 @@
<target name="-check-jmx-iiop-uptodate" depends="-init">
- <uptodate property="jmx-iiop-uptodate"
+ <uptodate property="jmx-iiop-uptodate"
srcfile="${classes.dir}/javax/management/remote/rmi/RMIConnectionImpl.class"
targetfile="${classes.dir}/org/omg/stub/javax/management/remote/rmi/_RMIConnectionImpl_Tie.class"
/>
- <uptodate property="jmx-iiop-uptodate"
+ <uptodate property="jmx-iiop-uptodate"
srcfile="${classes.dir}/javax/management/remote/rmi/RMIServerImpl.class"
targetfile="${classes.dir}/org/omg/stub/javax/management/remote/rmi/_RMIServerImpl_Tie.class"
/>
@@ -131,7 +131,7 @@
<target name="-post-compile" depends="-init,-rmic-jmx"
description="Jar JMX class files (including RMI stubs)" >
<mkdir dir="${dist.dir}/lib"/>
- <jar jarfile="${dist.dir}/lib/${jar.jmx.name}"
+ <jar jarfile="${dist.dir}/lib/${jar.jmx.name}"
update="true"
index="false"
duplicate="fail">
@@ -144,7 +144,7 @@
<attribute name="Specification-Version" value="${jar.jmx.spec.version}" />
<attribute name="Specification-Vendor" value="${jar.jmx.spec.vendor}" />
<attribute name="Implementation-Title" value="${jar.jmx.impl.title}" />
- <attribute name="Implementation-Version" value="${project.build.fulltag}" />
+ <attribute name="Implementation-Version" value="${project.build.fulltag}" />
<attribute name="Implementation-Vendor" value="${jar.jmx.impl.vendor}" />
</section>
</manifest>
--- a/src/share/classes/com/sun/jmx/defaults/ServiceName.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/defaults/ServiceName.java Tue Nov 11 09:07:58 2008 +0000
@@ -69,9 +69,9 @@ public class ServiceName {
/**
* The version of the JMX specification implemented by this product.
* <BR>
- * The value is <CODE>1.4</CODE>.
+ * The value is <CODE>2.0</CODE>.
*/
- public static final String JMX_SPEC_VERSION = "1.4";
+ public static final String JMX_SPEC_VERSION = "2.0";
/**
* The vendor of the JMX specification implemented by this product.
--- a/src/share/classes/com/sun/jmx/event/EventParams.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/event/EventParams.java Tue Nov 11 09:07:58 2008 +0000
@@ -41,7 +41,7 @@ public class EventParams {
@SuppressWarnings("cast") // cast for jdk 1.5
public static long getLeaseTimeout() {
- long timeout = EventClient.DEFAULT_LEASE_TIMEOUT;
+ long timeout = EventClient.DEFAULT_REQUESTED_LEASE_TIME;
try {
final GetPropertyAction act =
new GetPropertyAction(DEFAULT_LEASE_TIMEOUT);
--- a/src/share/classes/com/sun/jmx/event/LeaseManager.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/event/LeaseManager.java Tue Nov 11 09:07:58 2008 +0000
@@ -29,6 +29,7 @@ import java.util.concurrent.Executors;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
/**
@@ -141,11 +142,12 @@ public class LeaseManager {
}
private final Runnable callback;
- private ScheduledFuture scheduled; // If null, the lease has expired.
+ private ScheduledFuture<?> scheduled; // If null, the lease has expired.
+ private static final ThreadFactory threadFactory =
+ new DaemonThreadFactory("JMX LeaseManager %d");
private final ScheduledExecutorService executor
- = Executors.newScheduledThreadPool(1,
- new DaemonThreadFactory("JMX LeaseManager %d"));
+ = Executors.newScheduledThreadPool(1, threadFactory);
private static final ClassLogger logger =
new ClassLogger("javax.management.event", "LeaseManager");
--- a/src/share/classes/com/sun/jmx/event/LeaseRenewer.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/event/LeaseRenewer.java Tue Nov 11 09:07:58 2008 +0000
@@ -128,7 +128,7 @@ public class LeaseRenewer {
};
private final Callable<Long> doRenew;
- private ScheduledFuture future;
+ private ScheduledFuture<?> future;
private boolean closed = false;
private long nextRenewTime;
--- a/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java Tue Nov 11 09:07:58 2008 +0000
@@ -247,7 +247,7 @@ public class DefaultMBeanServerIntercept
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException, InstanceNotFoundException {
- Class theClass;
+ Class<?> theClass;
if (className == null) {
final RuntimeException wrapped =
@@ -327,7 +327,7 @@ public class DefaultMBeanServerIntercept
// ------------------------------
// ------------------------------
- Class theClass = object.getClass();
+ Class<?> theClass = object.getClass();
Introspector.checkCompliance(theClass);
@@ -808,9 +808,8 @@ public class DefaultMBeanServerIntercept
// on each specific attribute
//
allowedAttributes = new AttributeList(attributes.size());
- for (Iterator i = attributes.iterator(); i.hasNext();) {
+ for (Attribute attribute : attributes.asList()) {
try {
- Attribute attribute = (Attribute) i.next();
checkMBeanPermission(mbeanServerName, classname, attribute.getName(),
name, "setAttribute");
allowedAttributes.add(attribute);
@@ -1857,7 +1856,7 @@ public class DefaultMBeanServerIntercept
}
}
- private static void checkMBeanTrustPermission(final Class theClass)
+ private static void checkMBeanTrustPermission(final Class<?> theClass)
throws SecurityException {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
--- a/src/share/classes/com/sun/jmx/interceptor/SingleMBeanForwarder.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/interceptor/SingleMBeanForwarder.java Tue Nov 11 09:07:58 2008 +0000
@@ -55,9 +55,19 @@ import javax.management.namespace.MBeanS
import javax.management.namespace.MBeanServerSupport;
import javax.management.remote.IdentityMBeanServerForwarder;
+/**
+ * <p>An {@link MBeanServerForwarder} that simulates the existence of a
+ * given MBean. Requests for that MBean, call it X, are intercepted by the
+ * forwarder, and requests for any other MBean are forwarded to the next
+ * forwarder in the chain. Requests such as queryNames which can span both the
+ * X and other MBeans are handled by merging the results for X with the results
+ * from the next forwarder, unless the "visible" parameter is false, in which
+ * case X is invisible to such requests.</p>
+ */
public class SingleMBeanForwarder extends IdentityMBeanServerForwarder {
private final ObjectName mbeanName;
+ private final boolean visible;
private DynamicMBean mbean;
private MBeanServer mbeanMBS = new MBeanServerSupport() {
@@ -85,10 +95,20 @@ public class SingleMBeanForwarder extend
return null;
}
+ // This will only be called if mbeanName has an empty domain.
+ // In that case a getAttribute (e.g.) of that name will have the
+ // domain replaced by MBeanServerSupport with the default domain,
+ // so we must be sure that the default domain is empty too.
+ @Override
+ public String getDefaultDomain() {
+ return mbeanName.getDomain();
+ }
};
- public SingleMBeanForwarder(ObjectName mbeanName, DynamicMBean mbean) {
+ public SingleMBeanForwarder(
+ ObjectName mbeanName, DynamicMBean mbean, boolean visible) {
this.mbeanName = mbeanName;
+ this.visible = visible;
setSingleMBean(mbean);
}
@@ -213,8 +233,10 @@ public class SingleMBeanForwarder extend
@Override
public String[] getDomains() {
- TreeSet<String> domainSet =
- new TreeSet<String>(Arrays.asList(super.getDomains()));
+ String[] domains = super.getDomains();
+ if (!visible)
+ return domains;
+ TreeSet<String> domainSet = new TreeSet<String>(Arrays.asList(domains));
domainSet.add(mbeanName.getDomain());
return domainSet.toArray(new String[domainSet.size()]);
}
@@ -222,7 +244,7 @@ public class SingleMBeanForwarder extend
@Override
public Integer getMBeanCount() {
Integer count = super.getMBeanCount();
- if (!super.isRegistered(mbeanName))
+ if (visible && !super.isRegistered(mbeanName))
count++;
return count;
}
@@ -284,7 +306,7 @@ public class SingleMBeanForwarder extend
*/
private boolean applies(ObjectName pattern) {
// we know pattern is not null.
- if (!pattern.apply(mbeanName))
+ if (!visible || !pattern.apply(mbeanName))
return false;
final String dompat = pattern.getDomain();
@@ -306,10 +328,12 @@ public class SingleMBeanForwarder extend
@Override
public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) {
Set<ObjectInstance> names = super.queryMBeans(name, query);
- if (name == null || applies(name) ) {
- // Don't assume mbs.queryNames returns a writable set.
- names = Util.cloneSet(names);
- names.addAll(mbeanMBS.queryMBeans(name, query));
+ if (visible) {
+ if (name == null || applies(name) ) {
+ // Don't assume mbs.queryNames returns a writable set.
+ names = Util.cloneSet(names);
+ names.addAll(mbeanMBS.queryMBeans(name, query));
+ }
}
return names;
}
@@ -317,10 +341,12 @@ public class SingleMBeanForwarder extend
@Override
public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
Set<ObjectName> names = super.queryNames(name, query);
- if (name == null || applies(name)) {
- // Don't assume mbs.queryNames returns a writable set.
- names = Util.cloneSet(names);
- names.addAll(mbeanMBS.queryNames(name, query));
+ if (visible) {
+ if (name == null || applies(name)) {
+ // Don't assume mbs.queryNames returns a writable set.
+ names = Util.cloneSet(names);
+ names.addAll(mbeanMBS.queryNames(name, query));
+ }
}
return names;
}
--- a/src/share/classes/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java Tue Nov 11 09:07:58 2008 +0000
@@ -136,14 +136,14 @@ final class ClassLoaderRepositorySupport
new Hashtable<ObjectName,ClassLoader>(10);
// from javax.management.loading.DefaultLoaderRepository
- public final Class loadClass(String className)
+ public final Class<?> loadClass(String className)
throws ClassNotFoundException {
return loadClass(loaders, className, null, null);
}
// from javax.management.loading.DefaultLoaderRepository
- public final Class loadClassWithout(ClassLoader without, String className)
+ public final Class<?> loadClassWithout(ClassLoader without, String className)
throws ClassNotFoundException {
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
MBEANSERVER_LOGGER.logp(Level.FINER,
@@ -167,7 +167,7 @@ final class ClassLoaderRepositorySupport
}
- public final Class loadClassBefore(ClassLoader stop, String className)
+ public final Class<?> loadClassBefore(ClassLoader stop, String className)
throws ClassNotFoundException {
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
MBEANSERVER_LOGGER.logp(Level.FINER,
@@ -187,10 +187,10 @@ final class ClassLoaderRepositorySupport
}
- private Class loadClass(final LoaderEntry list[],
- final String className,
- final ClassLoader without,
- final ClassLoader stop)
+ private Class<?> loadClass(final LoaderEntry list[],
+ final String className,
+ final ClassLoader without,
+ final ClassLoader stop)
throws ClassNotFoundException {
final int size = list.length;
for(int i=0; i<size; i++) {
--- a/src/share/classes/com/sun/jmx/mbeanserver/ConvertingMethod.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/mbeanserver/ConvertingMethod.java Tue Nov 11 09:07:58 2008 +0000
@@ -68,12 +68,12 @@ final class ConvertingMethod {
return method.getName();
}
- OpenType getOpenReturnType() {
+ OpenType<?> getOpenReturnType() {
return returnMapping.getOpenType();
}
- OpenType[] getOpenParameterTypes() {
- final OpenType[] types = new OpenType[paramMappings.length];
+ OpenType<?>[] getOpenParameterTypes() {
+ final OpenType<?>[] types = new OpenType<?>[paramMappings.length];
for (int i = 0; i < paramMappings.length; i++)
types[i] = paramMappings[i].getOpenType();
return types;
--- a/src/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java Tue Nov 11 09:07:58 2008 +0000
@@ -26,7 +26,8 @@ package com.sun.jmx.mbeanserver;
package com.sun.jmx.mbeanserver;
import static com.sun.jmx.mbeanserver.Util.*;
-import java.lang.annotation.ElementType;
+import static com.sun.jmx.mbeanserver.MXBeanIntrospector.typeName;
+
import javax.management.openmbean.MXBeanMappingClass;
import static javax.management.openmbean.SimpleType.*;
@@ -120,7 +121,7 @@ import javax.management.openmbean.Tabula
*/
public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
static abstract class NonNullMXBeanMapping extends MXBeanMapping {
- NonNullMXBeanMapping(Type javaType, OpenType openType) {
+ NonNullMXBeanMapping(Type javaType, OpenType<?> openType) {
super(javaType, openType);
}
@@ -195,15 +196,15 @@ public class DefaultMXBeanMappingFactory
static {
/* Set up the mappings for Java types that map to SimpleType. */
- final OpenType[] simpleTypes = {
+ final OpenType<?>[] simpleTypes = {
BIGDECIMAL, BIGINTEGER, BOOLEAN, BYTE, CHARACTER, DATE,
DOUBLE, FLOAT, INTEGER, LONG, OBJECTNAME, SHORT, STRING,
VOID,
};
for (int i = 0; i < simpleTypes.length; i++) {
- final OpenType t = simpleTypes[i];
- Class c;
+ final OpenType<?> t = simpleTypes[i];
+ Class<?> c;
try {
c = Class.forName(t.getClassName(), false,
ObjectName.class.getClassLoader());
@@ -224,7 +225,7 @@ public class DefaultMXBeanMappingFactory
if (primitiveType != void.class) {
final Class<?> primitiveArrayType =
Array.newInstance(primitiveType, 0).getClass();
- final OpenType primitiveArrayOpenType =
+ final OpenType<?> primitiveArrayOpenType =
ArrayType.getPrimitiveArrayType(primitiveArrayType);
final MXBeanMapping primitiveArrayMapping =
new IdentityMapping(primitiveArrayType,
@@ -247,8 +248,10 @@ public class DefaultMXBeanMappingFactory
public synchronized MXBeanMapping mappingForType(Type objType,
MXBeanMappingFactory factory)
throws OpenDataException {
- if (inProgress.containsKey(objType))
- throw new OpenDataException("Recursive data structure");
+ if (inProgress.containsKey(objType)) {
+ throw new OpenDataException(
+ "Recursive data structure, including " + typeName(objType));
+ }
MXBeanMapping mapping;
@@ -259,6 +262,8 @@ public class DefaultMXBeanMappingFactory
inProgress.put(objType, objType);
try {
mapping = makeMapping(objType, factory);
+ } catch (OpenDataException e) {
+ throw openDataException("Cannot convert type: " + typeName(objType), e);
} finally {
inProgress.remove(objType);
}
@@ -285,13 +290,13 @@ public class DefaultMXBeanMappingFactory
Type componentType =
((GenericArrayType) objType).getGenericComponentType();
return makeArrayOrCollectionMapping(objType, componentType, factory);
- } else if (objType instanceof Class) {
+ } else if (objType instanceof Class<?>) {
Class<?> objClass = (Class<?>) objType;
if (objClass.isEnum()) {
// Huge hack to avoid compiler warnings here. The ElementType
// parameter is ignored but allows us to obtain a type variable
// T that matches <T extends Enum<T>>.
- return makeEnumMapping((Class) objClass, ElementType.class);
+ return makeEnumMapping((Class<?>) objClass, ElementType.class);
} else if (objClass.isArray()) {
Type componentType = objClass.getComponentType();
return makeArrayOrCollectionMapping(objClass, componentType,
@@ -354,7 +359,7 @@ public class DefaultMXBeanMappingFactory
}
private static <T extends Enum<T>> MXBeanMapping
- makeEnumMapping(Class enumClass, Class<T> fake) {
+ makeEnumMapping(Class<?> enumClass, Class<T> fake) {
return new EnumMapping<T>(Util.<Class<T>>cast(enumClass));
}
@@ -411,17 +416,17 @@ public class DefaultMXBeanMappingFactory
MXBeanMappingFactory factory)
throws OpenDataException {
- final String objTypeName = objType.toString();
+ final String objTypeName = typeName(objType);
final MXBeanMapping keyMapping = factory.mappingForType(keyType, factory);
final MXBeanMapping valueMapping = factory.mappingForType(valueType, factory);
- final OpenType keyOpenType = keyMapping.getOpenType();
- final OpenType valueOpenType = valueMapping.getOpenType();
+ final OpenType<?> keyOpenType = keyMapping.getOpenType();
+ final OpenType<?> valueOpenType = valueMapping.getOpenType();
final CompositeType rowType =
new CompositeType(objTypeName,
objTypeName,
keyValueArray,
keyValueArray,
- new OpenType[] {keyOpenType, valueOpenType});
+ new OpenType<?>[] {keyOpenType, valueOpenType});
final TabularType tabularType =
new TabularType(objTypeName, objTypeName, rowType, keyArray);
return new TabularMapping(objType, sortedMap, tabularType,
@@ -440,8 +445,8 @@ public class DefaultMXBeanMappingFactory
final Type rawType = objType.getRawType();
- if (rawType instanceof Class) {
- Class c = (Class<?>) rawType;
+ if (rawType instanceof Class<?>) {
+ Class<?> c = (Class<?>) rawType;
if (c == List.class || c == Set.class || c == SortedSet.class) {
Type[] actuals = objType.getActualTypeArguments();
assert(actuals.length == 1);
@@ -468,7 +473,7 @@ public class DefaultMXBeanMappingFactory
return new MXBeanRefMapping(t);
}
- private MXBeanMapping makeCompositeMapping(Class c,
+ private MXBeanMapping makeCompositeMapping(Class<?> c,
MXBeanMappingFactory factory)
throws OpenDataException {
@@ -514,7 +519,7 @@ public class DefaultMXBeanMappingFactory
final Method[] getters = new Method[nitems];
final String[] itemNames = new String[nitems];
- final OpenType[] openTypes = new OpenType[nitems];
+ final OpenType<?>[] openTypes = new OpenType<?>[nitems];
int i = 0;
for (Map.Entry<String,Method> entry : getterMap.entrySet()) {
itemNames[i] = entry.getKey();
@@ -546,7 +551,7 @@ public class DefaultMXBeanMappingFactory
can be directly represented by an ArrayType, and an int needs no mapping
because reflection takes care of it. */
private static final class IdentityMapping extends NonNullMXBeanMapping {
- IdentityMapping(Type targetType, OpenType openType) {
+ IdentityMapping(Type targetType, OpenType<?> openType) {
super(targetType, openType);
}
@@ -576,7 +581,7 @@ public class DefaultMXBeanMappingFactory
@Override
final Object toNonNullOpenValue(Object value) {
- return ((Enum) value).name();
+ return ((Enum<?>) value).name();
}
@Override
@@ -595,7 +600,7 @@ public class DefaultMXBeanMappingFactory
private static final class ArrayMapping extends NonNullMXBeanMapping {
ArrayMapping(Type targetType,
- ArrayType openArrayType, Class openArrayClass,
+ ArrayType<?> openArrayType, Class<?> openArrayClass,
MXBeanMapping elementMapping) {
super(targetType, openArrayType);
this.elementMapping = elementMapping;
@@ -623,7 +628,7 @@ public class DefaultMXBeanMappingFactory
if (javaType instanceof GenericArrayType) {
componentType =
((GenericArrayType) javaType).getGenericComponentType();
- } else if (javaType instanceof Class &&
+ } else if (javaType instanceof Class<?> &&
((Class<?>) javaType).isArray()) {
componentType = ((Class<?>) javaType).getComponentType();
} else {
@@ -651,8 +656,8 @@ public class DefaultMXBeanMappingFactory
private static final class CollectionMapping extends NonNullMXBeanMapping {
CollectionMapping(Type targetType,
- ArrayType openArrayType,
- Class openArrayClass,
+ ArrayType<?> openArrayType,
+ Class<?> openArrayClass,
MXBeanMapping elementMapping) {
super(targetType, openArrayType);
this.elementMapping = elementMapping;
@@ -662,26 +667,28 @@ public class DefaultMXBeanMappingFactory
and all Sets to TreeSet. (TreeSet because it is a SortedSet,
so works for both Set and SortedSet.) */
Type raw = ((ParameterizedType) targetType).getRawType();
- Class c = (Class<?>) raw;
+ Class<?> c = (Class<?>) raw;
+ final Class<?> collC;
if (c == List.class)
- collectionClass = ArrayList.class;
+ collC = ArrayList.class;
else if (c == Set.class)
- collectionClass = HashSet.class;
+ collC = HashSet.class;
else if (c == SortedSet.class)
- collectionClass = TreeSet.class;
+ collC = TreeSet.class;
else { // can't happen
assert(false);
- collectionClass = null;
- }
+ collC = null;
+ }
+ collectionClass = Util.cast(collC);
}
@Override
final Object toNonNullOpenValue(Object value)
throws OpenDataException {
- final Collection valueCollection = (Collection) value;
- if (valueCollection instanceof SortedSet) {
- Comparator comparator =
- ((SortedSet) valueCollection).comparator();
+ final Collection<?> valueCollection = (Collection<?>) value;
+ if (valueCollection instanceof SortedSet<?>) {
+ Comparator<?> comparator =
+ ((SortedSet<?>) valueCollection).comparator();
if (comparator != null) {
final String msg =
"Cannot convert SortedSet with non-null comparator: " +
@@ -725,7 +732,7 @@ public class DefaultMXBeanMappingFactory
elementMapping.checkReconstructible();
}
- private final Class<? extends Collection> collectionClass;
+ private final Class<? extends Collection<?>> collectionClass;
private final MXBeanMapping elementMapping;
}
@@ -794,8 +801,8 @@ public class DefaultMXBeanMappingFactory
@Override
final Object toNonNullOpenValue(Object value) throws OpenDataException {
final Map<Object, Object> valueMap = cast(value);
- if (valueMap instanceof SortedMap) {
- Comparator comparator = ((SortedMap) valueMap).comparator();
+ if (valueMap instanceof SortedMap<?,?>) {
+ Comparator<?> comparator = ((SortedMap<?,?>) valueMap).comparator();
if (comparator != null) {
final String msg =
"Cannot convert SortedMap with non-null comparator: " +
@@ -806,7 +813,7 @@ public class DefaultMXBeanMappingFactory
final TabularType tabularType = (TabularType) getOpenType();
final TabularData table = new TabularDataSupport(tabularType);
final CompositeType rowType = tabularType.getRowType();
- for (Map.Entry entry : valueMap.entrySet()) {
+ for (Map.Entry<Object, Object> entry : valueMap.entrySet()) {
final Object openKey = keyMapping.toOpenValue(entry.getKey());
final Object openValue = valueMapping.toOpenValue(entry.getValue());
final CompositeData row;
@@ -852,7 +859,7 @@ public class DefaultMXBeanMappingFactory
}
private final class CompositeMapping extends NonNullMXBeanMapping {
- CompositeMapping(Class targetClass,
+ CompositeMapping(Class<?> targetClass,
CompositeType compositeType,
String[] itemNames,
Method[] getters,
@@ -901,7 +908,7 @@ public class DefaultMXBeanMappingFactory
if (compositeBuilder != null)
return;
- Class targetClass = (Class<?>) getJavaType();
+ Class<?> targetClass = (Class<?>) getJavaType();
/* In this 2D array, each subarray is a set of builders where
there is no point in consulting the ones after the first if
the first refuses. */
@@ -924,6 +931,7 @@ public class DefaultMXBeanMappingFactory
concatenating each Builder's explanation of why it
isn't applicable. */
final StringBuilder whyNots = new StringBuilder();
+ Throwable possibleCause = null;
find:
for (CompositeBuilder[] relatedBuilders : builders) {
for (int i = 0; i < relatedBuilders.length; i++) {
@@ -933,6 +941,9 @@ public class DefaultMXBeanMappingFactory
foundBuilder = builder;
break find;
}
+ Throwable cause = builder.possibleCause();
+ if (cause != null)
+ possibleCause = cause;
if (whyNot.length() > 0) {
if (whyNots.length() > 0)
whyNots.append("; ");
@@ -943,10 +954,12 @@ public class DefaultMXBeanMappingFactory
}
}
if (foundBuilder == null) {
- final String msg =
+ String msg =
"Do not know how to make a " + targetClass.getName() +
" from a CompositeData: " + whyNots;
- throw new InvalidObjectException(msg);
+ if (possibleCause != null)
+ msg += ". Remaining exceptions show a POSSIBLE cause.";
+ throw invalidObjectException(msg, possibleCause);
}
compositeBuilder = foundBuilder;
}
@@ -973,7 +986,7 @@ public class DefaultMXBeanMappingFactory
/** Converts from a CompositeData to an instance of the targetClass. */
private static abstract class CompositeBuilder {
- CompositeBuilder(Class targetClass, String[] itemNames) {
+ CompositeBuilder(Class<?> targetClass, String[] itemNames) {
this.targetClass = targetClass;
this.itemNames = itemNames;
}
@@ -994,6 +1007,16 @@ public class DefaultMXBeanMappingFactory
abstract String applicable(Method[] getters)
throws InvalidObjectException;
+ /** If the subclass returns an explanation of why it is not applicable,
+ it can additionally indicate an exception with details. This is
+ potentially confusing, because the real problem could be that one
+ of the other subclasses is supposed to be applicable but isn't.
+ But the advantage of less information loss probably outweighs the
+ disadvantage of possible confusion. */
+ Throwable possibleCause() {
+ return null;
+ }
+
abstract Object fromCompositeData(CompositeData cd,
String[] itemNames,
MXBeanMapping[] converters)
@@ -1008,7 +1031,7 @@ public class DefaultMXBeanMappingFactory
private static final class CompositeBuilderViaFrom
extends CompositeBuilder {
- CompositeBuilderViaFrom(Class targetClass, String[] itemNames) {
+ CompositeBuilderViaFrom(Class<?> targetClass, String[] itemNames) {
super(targetClass, itemNames);
}
@@ -1018,8 +1041,7 @@ public class DefaultMXBeanMappingFactory
Class<?> targetClass = getTargetClass();
try {
Method fromMethod =
- targetClass.getMethod("from",
- new Class[] {CompositeData.class});
+ targetClass.getMethod("from", CompositeData.class);
if (!Modifier.isStatic(fromMethod.getModifiers())) {
final String msg =
@@ -1030,8 +1052,8 @@ public class DefaultMXBeanMappingFactory
if (fromMethod.getReturnType() != getTargetClass()) {
final String msg =
"Method from(CompositeData) returns " +
- fromMethod.getReturnType().getName() +
- " not " + targetClass.getName();
+ typeName(fromMethod.getReturnType()) +
+ " not " + typeName(targetClass);
throw new InvalidObjectException(msg);
}
@@ -1071,7 +1093,7 @@ public class DefaultMXBeanMappingFactory
If all the getters are OK, then the "applicable" method will return
an empty string and the other builders will be tried. */
private static class CompositeBuilderCheckGetters extends CompositeBuilder {
- CompositeBuilderCheckGetters(Class targetClass, String[] itemNames,
+ CompositeBuilderCheckGetters(Class<?> targetClass, String[] itemNames,
MXBeanMapping[] getterConverters) {
super(targetClass, itemNames);
this.getterConverters = getterConverters;
@@ -1082,11 +1104,17 @@ public class DefaultMXBeanMappingFactory
try {
getterConverters[i].checkReconstructible();
} catch (InvalidObjectException e) {
+ possibleCause = e;
return "method " + getters[i].getName() + " returns type " +
"that cannot be mapped back from OpenData";
}
}
return "";
+ }
+
+ @Override
+ Throwable possibleCause() {
+ return possibleCause;
}
final Object fromCompositeData(CompositeData cd,
@@ -1096,6 +1124,7 @@ public class DefaultMXBeanMappingFactory
}
private final MXBeanMapping[] getterConverters;
+ private Throwable possibleCause;
}
/** Builder for when the target class has a setter for every getter. */
@@ -1115,7 +1144,7 @@ public class DefaultMXBeanMappingFactory
Method[] setters = new Method[getters.length];
for (int i = 0; i < getters.length; i++) {
Method getter = getters[i];
- Class returnType = getter.getReturnType();
+ Class<?> returnType = getter.getReturnType();
String name = propertyName(getter);
String setterName = "set" + name;
Method setter;
@@ -1163,7 +1192,7 @@ public class DefaultMXBeanMappingFactory
private static final class CompositeBuilderViaConstructor
extends CompositeBuilder {
- CompositeBuilderViaConstructor(Class targetClass, String[] itemNames) {
+ CompositeBuilderViaConstructor(Class<?> targetClass, String[] itemNames) {
super(targetClass, itemNames);
}
@@ -1171,7 +1200,7 @@ public class DefaultMXBeanMappingFactory
final Class<ConstructorProperties> propertyNamesClass = ConstructorProperties.class;
- Class targetClass = getTargetClass();
+ Class<?> targetClass = getTargetClass();
Constructor<?>[] constrs = targetClass.getConstructors();
// Applicable if and only if there are any annotated constructors
@@ -1226,10 +1255,16 @@ public class DefaultMXBeanMappingFactory
for (int i = 0; i < propertyNames.length; i++) {
String propertyName = propertyNames[i];
if (!getterMap.containsKey(propertyName)) {
- final String msg =
+ String msg =
"@ConstructorProperties includes name " + propertyName +
- " which does not correspond to a property: " +
- constr;
+ " which does not correspond to a property";
+ for (String getterName : getterMap.keySet()) {
+ if (getterName.equalsIgnoreCase(propertyName)) {
+ msg += " (differs only in case from property " +
+ getterName + ")";
+ }
+ }
+ msg += ": " + constr;
throw new InvalidObjectException(msg);
}
int getterIndex = getterMap.get(propertyName);
@@ -1384,12 +1419,12 @@ public class DefaultMXBeanMappingFactory
private static final class CompositeBuilderViaProxy
extends CompositeBuilder {
- CompositeBuilderViaProxy(Class targetClass, String[] itemNames) {
+ CompositeBuilderViaProxy(Class<?> targetClass, String[] itemNames) {
super(targetClass, itemNames);
}
String applicable(Method[] getters) {
- Class targetClass = getTargetClass();
+ Class<?> targetClass = getTargetClass();
if (!targetClass.isInterface())
return "not an interface";
Set<Method> methods =
@@ -1401,7 +1436,7 @@ public class DefaultMXBeanMappingFactory
String bad = null;
for (Method m : methods) {
String mname = m.getName();
- Class[] mparams = m.getParameterTypes();
+ Class<?>[] mparams = m.getParameterTypes();
try {
Method om = Object.class.getMethod(mname, mparams);
if (!Modifier.isPublic(om.getModifiers()))
@@ -1422,10 +1457,10 @@ public class DefaultMXBeanMappingFactory
final Object fromCompositeData(CompositeData cd,
String[] itemNames,
MXBeanMapping[] converters) {
- final Class targetClass = getTargetClass();
+ final Class<?> targetClass = getTargetClass();
return
Proxy.newProxyInstance(targetClass.getClassLoader(),
- new Class[] {targetClass},
+ new Class<?>[] {targetClass},
new CompositeDataInvocationHandler(cd));
}
}
@@ -1447,9 +1482,9 @@ public class DefaultMXBeanMappingFactory
return openDataException(cause.getMessage(), cause);
}
- static void mustBeComparable(Class collection, Type element)
+ static void mustBeComparable(Class<?> collection, Type element)
throws OpenDataException {
- if (!(element instanceof Class)
+ if (!(element instanceof Class<?>)
|| !Comparable.class.isAssignableFrom((Class<?>) element)) {
final String msg =
"Parameter class " + element + " of " +
--- a/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java Tue Nov 11 09:07:58 2008 +0000
@@ -115,7 +115,7 @@ public class Introspector {
* Dynamic MBeans, <code>false</code> otherwise.
*
**/
- public static final boolean isDynamic(final Class c) {
+ public static final boolean isDynamic(final Class<?> c) {
// Check if the MBean implements the DynamicMBean interface
return javax.management.DynamicMBean.class.isAssignableFrom(c);
}
@@ -134,7 +134,7 @@ public class Introspector {
* MBeanServer.
*
**/
- public static void testCreation(Class c)
+ public static void testCreation(Class<?> c)
throws NotCompliantMBeanException {
// Check if the class is a concrete class
final int mods = c.getModifiers();
@@ -143,7 +143,7 @@ public class Introspector {
}
// Check if the MBean has a public constructor
- final Constructor[] consList = c.getConstructors();
+ final Constructor<?>[] consList = c.getConstructors();
if (consList.length == 0) {
throw new NotCompliantMBeanException("MBean class must have public constructor");
}
@@ -253,7 +253,7 @@ public class Introspector {
* @exception NotCompliantMBeanException The specified class is not a
* JMX compliant MBean
*/
- public static MBeanInfo testCompliance(Class baseClass)
+ public static MBeanInfo testCompliance(Class<?> baseClass)
throws NotCompliantMBeanException {
// ------------------------------
@@ -267,7 +267,7 @@ public class Introspector {
return testCompliance(baseClass, null);
}
- public static void testComplianceMXBeanInterface(Class interfaceClass,
+ public static void testComplianceMXBeanInterface(Class<?> interfaceClass,
MXBeanMappingFactory factory)
throws NotCompliantMBeanException {
MXBeanIntrospector.getInstance(factory).getAnalyzer(interfaceClass);
@@ -596,10 +596,10 @@ public class Introspector {
ss[i] = (String) annotationToField(xx[i]);
return ss;
}
- if (x instanceof Class)
+ if (x instanceof Class<?>)
return ((Class<?>) x).getName();
- if (x instanceof Enum)
- return ((Enum) x).name();
+ if (x instanceof Enum<?>)
+ return ((Enum<?>) x).name();
// The only other possibility is that the value is another
// annotation, or that the language has evolved since this code
// was written. We don't allow for either of those currently.
--- a/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java Tue Nov 11 09:07:58 2008 +0000
@@ -33,6 +33,7 @@ import java.security.Permission;
import java.security.Permission;
import java.security.PrivilegedExceptionAction;
import java.util.Iterator;
+import java.util.List;
import java.util.Set;
import java.util.logging.Level;
@@ -121,7 +122,7 @@ public final class JmxMBeanServer
* {@link javax.management.MBeanServerFactory#newMBeanServer(java.lang.String)}
* instead.
* <p>
- * By default, {@link MBeanServerInterceptor} are disabled. Use
+ * By default, interceptors are disabled. Use
* {@link #JmxMBeanServer(java.lang.String,javax.management.MBeanServer,javax.management.MBeanServerDelegate,boolean)} to enable them.
* </ul>
* @param domain The default domain name used by this MBeanServer.
@@ -238,7 +239,7 @@ public final class JmxMBeanServer
this.mBeanServerDelegateObject = delegate;
this.outerShell = outer;
- final Repository repository = new Repository(domain,fairLock);
+ final Repository repository = new Repository(domain);
this.mbsInterceptor =
new NamespaceDispatchInterceptor(outer, delegate, instantiator,
repository);
@@ -1144,7 +1145,7 @@ public final class JmxMBeanServer
// This call requires MBeanPermission 'getClassLoaderRepository'
final ClassLoaderRepository clr = getClassLoaderRepository();
- Class theClass;
+ Class<?> theClass;
try {
if (clr == null) throw new ClassNotFoundException(className);
theClass = clr.loadClass(className);
@@ -1457,23 +1458,22 @@ public final class JmxMBeanServer
*/
private AttributeList cloneAttributeList(AttributeList list) {
if (list != null) {
+ List<Attribute> alist = list.asList();
if (!list.getClass().equals(AttributeList.class)) {
// Create new attribute list
//
- AttributeList newList = new AttributeList(list.size());
+ AttributeList newList = new AttributeList(alist.size());
// Iterate through list and replace non JMX attributes
//
- for (Iterator i = list.iterator(); i.hasNext(); ) {
- Attribute attribute = (Attribute) i.next();
+ for (Attribute attribute : alist)
newList.add(cloneAttribute(attribute));
- }
return newList;
} else {
// Iterate through list and replace non JMX attributes
//
- for (int i = 0; i < list.size(); i++) {
- Attribute attribute = (Attribute) list.get(i);
+ for (int i = 0; i < alist.size(); i++) {
+ Attribute attribute = alist.get(i);
if (!attribute.getClass().equals(Attribute.class)) {
list.set(i, cloneAttribute(attribute));
}
--- a/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java Tue Nov 11 09:07:58 2008 +0000
@@ -70,7 +70,7 @@ public class MBeanInstantiator {
* instantiate an MBean of this class in the MBeanServer.
* e.g. it must have a public constructor, be a concrete class...
*/
- public void testCreation(Class c) throws NotCompliantMBeanException {
+ public void testCreation(Class<?> c) throws NotCompliantMBeanException {
Introspector.testCreation(c);
}
@@ -78,10 +78,10 @@ public class MBeanInstantiator {
* Loads the class with the specified name using this object's
* Default Loader Repository.
**/
- public Class findClassWithDefaultLoaderRepository(String className)
+ public Class<?> findClassWithDefaultLoaderRepository(String className)
throws ReflectionException {
- Class theClass;
+ Class<?> theClass;
if (className == null) {
throw new RuntimeOperationsException(new
IllegalArgumentException("The class name cannot be null"),
@@ -105,7 +105,7 @@ public class MBeanInstantiator {
* Gets the class for the specified class name using the MBean
* Interceptor's classloader
*/
- public Class findClass(String className, ClassLoader loader)
+ public Class<?> findClass(String className, ClassLoader loader)
throws ReflectionException {
return loadClass(className,loader);
@@ -115,7 +115,7 @@ public class MBeanInstantiator {
* Gets the class for the specified class name using the specified
* class loader
*/
- public Class findClass(String className, ObjectName aLoader)
+ public Class<?> findClass(String className, ObjectName aLoader)
throws ReflectionException, InstanceNotFoundException {
if (aLoader == null)
@@ -140,14 +140,14 @@ public class MBeanInstantiator {
* Return an array of Class corresponding to the given signature, using
* the specified class loader.
*/
- public Class[] findSignatureClasses(String signature[],
- ClassLoader loader)
- throws ReflectionException {
+ public Class<?>[] findSignatureClasses(String signature[],
+ ClassLoader loader)
+ throws ReflectionException {
if (signature == null) return null;
final ClassLoader aLoader = loader;
final int length= signature.length;
- final Class tab[]=new Class[length];
+ final Class<?> tab[]=new Class<?>[length];
if (length == 0) return tab;
try {
@@ -156,7 +156,7 @@ public class MBeanInstantiator {
// forth)
//
- final Class primCla = primitiveClasses.get(signature[i]);
+ final Class<?> primCla = primitiveClasses.get(signature[i]);
if (primCla != null) {
tab[i] = primCla;
continue;
@@ -203,14 +203,14 @@ public class MBeanInstantiator {
* Instantiates an object given its class, using its empty constructor.
* The call returns a reference to the newly created object.
*/
- public Object instantiate(Class theClass)
+ public Object instantiate(Class<?> theClass)
throws ReflectionException, MBeanException {
Object moi;
// ------------------------------
// ------------------------------
- Constructor cons = findConstructor(theClass, null);
+ Constructor<?> cons = findConstructor(theClass, null);
if (cons == null) {
throw new ReflectionException(new
NoSuchMethodException("No such constructor"));
@@ -257,14 +257,14 @@ public class MBeanInstantiator {
* signature of its constructor The call returns a reference to
* the newly created object.
*/
- public Object instantiate(Class theClass, Object params[],
+ public Object instantiate(Class<?> theClass, Object params[],
String signature[], ClassLoader loader)
throws ReflectionException, MBeanException {
// Instantiate the new object
// ------------------------------
// ------------------------------
- final Class[] tab;
+ final Class<?>[] tab;
Object moi;
try {
// Build the signature of the method
@@ -283,7 +283,7 @@ public class MBeanInstantiator {
}
// Query the metadata service to get the right constructor
- Constructor cons = findConstructor(theClass, tab);
+ Constructor<?> cons = findConstructor(theClass, tab);
if (cons == null) {
throw new ReflectionException(new
@@ -407,7 +407,7 @@ public class MBeanInstantiator {
throw new RuntimeOperationsException(new
IllegalArgumentException(), "Null className passed in parameter");
}
- Class theClass;
+ Class<?> theClass;
if (loaderName == null) {
// Load the class using the agent class loader
theClass = findClass(className, loader);
@@ -547,7 +547,7 @@ public class MBeanInstantiator {
throws ReflectionException,
MBeanException {
- Class theClass = findClassWithDefaultLoaderRepository(className);
+ Class<?> theClass = findClassWithDefaultLoaderRepository(className);
return instantiate(theClass, params, signature, loader);
}
@@ -595,7 +595,7 @@ public class MBeanInstantiator {
// ------------------------------
// ------------------------------
- Class theClass;
+ Class<?> theClass;
if (loaderName == null) {
theClass = findClass(className, loader);
@@ -617,10 +617,10 @@ public class MBeanInstantiator {
* Load a class with the specified loader, or with this object
* class loader if the specified loader is null.
**/
- static Class loadClass(String className, ClassLoader loader)
+ static Class<?> loadClass(String className, ClassLoader loader)
throws ReflectionException {
- Class theClass;
+ Class<?> theClass;
if (className == null) {
throw new RuntimeOperationsException(new
IllegalArgumentException("The class name cannot be null"),
@@ -647,15 +647,15 @@ public class MBeanInstantiator {
* Load the classes specified in the signature with the given loader,
* or with this object class loader.
**/
- static Class[] loadSignatureClasses(String signature[],
- ClassLoader loader)
+ static Class<?>[] loadSignatureClasses(String signature[],
+ ClassLoader loader)
throws ReflectionException {
if (signature == null) return null;
final ClassLoader aLoader =
(loader==null?MBeanInstantiator.class.getClassLoader():loader);
final int length= signature.length;
- final Class tab[]=new Class[length];
+ final Class<?> tab[]=new Class<?>[length];
if (length == 0) return tab;
try {
@@ -664,7 +664,7 @@ public class MBeanInstantiator {
// forth)
//
- final Class primCla = primitiveClasses.get(signature[i]);
+ final Class<?> primCla = primitiveClasses.get(signature[i]);
if (primCla != null) {
tab[i] = primCla;
continue;
@@ -710,9 +710,9 @@ public class MBeanInstantiator {
private static final Map<String, Class<?>> primitiveClasses = Util.newMap();
static {
- for (Class<?> c : new Class[] {byte.class, short.class, int.class,
- long.class, float.class, double.class,
- char.class, boolean.class})
+ for (Class<?> c : new Class<?>[] {byte.class, short.class, int.class,
+ long.class, float.class, double.class,
+ char.class, boolean.class})
primitiveClasses.put(c.getName(), c);
}
}
--- a/src/share/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java Tue Nov 11 09:07:58 2008 +0000
@@ -160,7 +160,7 @@ class MXBeanIntrospector extends MBeanIn
// matched to the corresponding Java type, except when that
// type is primitive.
Type t = m.getGenericParameterTypes()[paramNo];
- return (!(t instanceof Class) || !((Class) t).isPrimitive());
+ return (!(t instanceof Class<?>) || !((Class<?>) t).isPrimitive());
} else {
Object v;
try {
@@ -354,7 +354,7 @@ class MXBeanIntrospector extends MBeanIn
}
}
- private static Descriptor typeDescriptor(OpenType openType,
+ private static Descriptor typeDescriptor(OpenType<?> openType,
Type originalType) {
return new ImmutableDescriptor(
new String[] {"openType",
@@ -380,37 +380,37 @@ class MXBeanIntrospector extends MBeanIn
if (type instanceof GenericArrayType) {
return canUseOpenInfo(
((GenericArrayType) type).getGenericComponentType());
- } else if (type instanceof Class && ((Class<?>) type).isArray()) {
+ } else if (type instanceof Class<?> && ((Class<?>) type).isArray()) {
return canUseOpenInfo(
((Class<?>) type).getComponentType());
}
- return (!(type instanceof Class && ((Class<?>) type).isPrimitive()));
+ return (!(type instanceof Class<?> && ((Class<?>) type).isPrimitive()));
}
private static String originalTypeString(Type type) {
- if (type instanceof Class)
- return ((Class) type).getName();
+ if (type instanceof Class<?>)
+ return ((Class<?>) type).getName();
else
- return genericTypeString(type);
- }
-
- private static String genericTypeString(Type type) {
+ return typeName(type);
+ }
+
+ static String typeName(Type type) {
if (type instanceof Class<?>) {
Class<?> c = (Class<?>) type;
if (c.isArray())
- return genericTypeString(c.getComponentType()) + "[]";
+ return typeName(c.getComponentType()) + "[]";
else
return c.getName();
} else if (type instanceof GenericArrayType) {
GenericArrayType gat = (GenericArrayType) type;
- return genericTypeString(gat.getGenericComponentType()) + "[]";
+ return typeName(gat.getGenericComponentType()) + "[]";
} else if (type instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) type;
StringBuilder sb = new StringBuilder();
- sb.append(genericTypeString(pt.getRawType())).append("<");
+ sb.append(typeName(pt.getRawType())).append("<");
String sep = "";
for (Type t : pt.getActualTypeArguments()) {
- sb.append(sep).append(genericTypeString(t));
+ sb.append(sep).append(typeName(t));
sep = ", ";
}
return sb.append(">").toString();
--- a/src/share/classes/com/sun/jmx/mbeanserver/ObjectInputStreamWithLoader.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/mbeanserver/ObjectInputStreamWithLoader.java Tue Nov 11 09:07:58 2008 +0000
@@ -54,7 +54,8 @@ class ObjectInputStreamWithLoader extend
this.loader = theLoader;
}
- protected Class resolveClass(ObjectStreamClass aClass)
+ @Override
+ protected Class<?> resolveClass(ObjectStreamClass aClass)
throws IOException, ClassNotFoundException {
if (loader == null) {
return super.resolveClass(aClass);
--- a/src/share/classes/com/sun/jmx/mbeanserver/SecureClassLoaderRepository.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/mbeanserver/SecureClassLoaderRepository.java Tue Nov 11 09:07:58 2008 +0000
@@ -47,16 +47,16 @@ final class SecureClassLoaderRepository
public SecureClassLoaderRepository(ClassLoaderRepository clr) {
this.clr=clr;
}
- public final Class loadClass(String className)
+ public final Class<?> loadClass(String className)
throws ClassNotFoundException {
return clr.loadClass(className);
}
- public final Class loadClassWithout(ClassLoader loader,
+ public final Class<?> loadClassWithout(ClassLoader loader,
String className)
throws ClassNotFoundException {
return clr.loadClassWithout(loader,className);
}
- public final Class loadClassBefore(ClassLoader loader,
+ public final Class<?> loadClassBefore(ClassLoader loader,
String className)
throws ClassNotFoundException {
return clr.loadClassBefore(loader,className);
--- a/src/share/classes/com/sun/jmx/mbeanserver/Util.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/mbeanserver/Util.java Tue Nov 11 09:07:58 2008 +0000
@@ -669,7 +669,7 @@ public class Util {
}
public static <T> Set<T> cloneSet(Set<T> set) {
- if (set instanceof SortedSet) {
+ if (set instanceof SortedSet<?>) {
@SuppressWarnings("unchecked")
SortedSet<T> sset = (SortedSet<T>) set;
set = new TreeSet<T>(sset.comparator());
@@ -680,7 +680,7 @@ public class Util {
}
public static <T> Set<T> equivalentEmptySet(Set<T> set) {
- if (set instanceof SortedSet) {
+ if (set instanceof SortedSet<?>) {
@SuppressWarnings("unchecked")
SortedSet<T> sset = (SortedSet<T>) set;
set = new TreeSet<T>(sset.comparator());
--- a/src/share/classes/com/sun/jmx/mbeanserver/WeakIdentityHashMap.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/mbeanserver/WeakIdentityHashMap.java Tue Nov 11 09:07:58 2008 +0000
@@ -118,9 +118,9 @@ class WeakIdentityHashMap<K, V> {
public boolean equals(Object o) {
if (this == o)
return true;
- if (!(o instanceof IdentityWeakReference))
+ if (!(o instanceof IdentityWeakReference<?>))
return false;
- IdentityWeakReference wr = (IdentityWeakReference) o;
+ IdentityWeakReference<?> wr = (IdentityWeakReference<?>) o;
Object got = get();
return (got != null && got == wr.get());
}
--- a/src/share/classes/com/sun/jmx/namespace/ObjectNameRouter.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/namespace/ObjectNameRouter.java Tue Nov 11 09:07:58 2008 +0000
@@ -48,11 +48,6 @@ public class ObjectNameRouter {
final int slen;
final int tlen;
final boolean identity;
-
-
- public ObjectNameRouter(String targetDirName) {
- this(targetDirName,null);
- }
/** Creates a new instance of ObjectNameRouter */
public ObjectNameRouter(final String remove, final String add) {
@@ -186,6 +181,4 @@ public class ObjectNameRouter {
b.append(NAMESPACE_SEPARATOR);
return b.toString();
}
-
-
}
--- a/src/share/classes/com/sun/jmx/namespace/RoutingConnectionProxy.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/namespace/RoutingConnectionProxy.java Tue Nov 11 09:07:58 2008 +0000
@@ -31,7 +31,6 @@ import java.util.logging.Logger;
import java.util.logging.Logger;
import javax.management.MBeanServerConnection;
-import javax.management.namespace.JMXNamespaces;
/**
@@ -61,18 +60,10 @@ public class RoutingConnectionProxy
* Creates a new instance of RoutingConnectionProxy
*/
public RoutingConnectionProxy(MBeanServerConnection source,
- String sourceDir) {
- this(source,sourceDir,"",false);
- }
-
- /**
- * Creates a new instance of RoutingConnectionProxy
- */
- public RoutingConnectionProxy(MBeanServerConnection source,
String sourceDir,
String targetDir,
- boolean forwardsContext) {
- super(source,sourceDir,targetDir,forwardsContext);
+ boolean probe) {
+ super(source, sourceDir, targetDir, probe);
if (LOG.isLoggable(Level.FINER))
LOG.finer("RoutingConnectionProxy for " + getSourceNamespace() +
@@ -85,15 +76,13 @@ public class RoutingConnectionProxy
final String sourceNs = getSourceNamespace();
String wrapped = String.valueOf(source());
if ("".equals(targetNs)) {
- if (forwardsContext)
- wrapped = "ClientContext.withDynamicContext("+wrapped+")";
return "JMXNamespaces.narrowToNamespace("+
wrapped+", \""+
sourceNs+"\")";
}
return this.getClass().getSimpleName()+"("+wrapped+", \""+
sourceNs+"\", \""+
- targetNs+"\", "+forwardsContext+")";
+ targetNs+"\")";
}
static final RoutingProxyFactory
@@ -102,22 +91,16 @@ public class RoutingConnectionProxy
<MBeanServerConnection,RoutingConnectionProxy>() {
public RoutingConnectionProxy newInstance(MBeanServerConnection source,
- String sourcePath, String targetPath,
- boolean forwardsContext) {
+ String sourcePath, String targetPath, boolean probe) {
return new RoutingConnectionProxy(source,sourcePath,
- targetPath,forwardsContext);
- }
-
- public RoutingConnectionProxy newInstance(
- MBeanServerConnection source, String sourcePath) {
- return new RoutingConnectionProxy(source,sourcePath);
+ targetPath, probe);
}
};
- public static MBeanServerConnection cd(MBeanServerConnection source,
- String sourcePath) {
+ public static MBeanServerConnection cd(
+ MBeanServerConnection source, String sourcePath, boolean probe) {
return RoutingProxy.cd(RoutingConnectionProxy.class, FACTORY,
- source, sourcePath);
+ source, sourcePath, probe);
}
}
--- a/src/share/classes/com/sun/jmx/namespace/RoutingProxy.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/namespace/RoutingProxy.java Tue Nov 11 09:07:58 2008 +0000
@@ -30,6 +30,7 @@ import java.util.logging.Level;
import java.util.logging.Level;
import java.util.logging.Logger;
+import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanRegistrationException;
@@ -90,17 +91,9 @@ import javax.management.namespace.JMXNam
// 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
+// factory method that can concatenate namespace paths in order to
// return a single RoutingProxy - rather than wrapping a RoutingProxy inside
// another RoutingProxy. See RoutingConnectionProxy.cd and
// RoutingServerProxy.cd
@@ -146,25 +139,27 @@ public abstract class RoutingProxy<T ext
private final T source;
// The name space we're narrowing to (usually some name space in
- // the source MBeanServerConnection
+ // the source MBeanServerConnection), e.g. "a" for the namespace
+ // "a//". This is empty in the case of ClientContext described above.
private final String sourceNs;
- // The name space we pretend to be mounted in (usually "")
+ // The name space we pretend to be mounted in. This is empty except
+ // in the case of ClientContext described above (where it will be
+ // something like "jmx.context//foo=bar".
private final String targetNs;
// The name of the JMXNamespace that handles the source name space
private final ObjectName handlerName;
private final ObjectNameRouter router;
- final boolean forwardsContext;
private volatile String defaultDomain = null;
/**
* Creates a new instance of RoutingProxy
*/
protected RoutingProxy(T source,
- String sourceNs,
- String targetNs,
- boolean forwardsContext) {
+ String sourceNs,
+ String targetNs,
+ boolean probe) {
if (source == null) throw new IllegalArgumentException("null");
this.sourceNs = JMXNamespaces.normalizeNamespaceName(sourceNs);
@@ -177,13 +172,17 @@ public abstract class RoutingProxy<T ext
// System.err.println("sourceNs: "+sourceNs);
this.handlerName =
JMXNamespaces.getNamespaceObjectName(this.sourceNs);
- try {
- // System.err.println("handlerName: "+handlerName);
- if (!source.isRegistered(handlerName))
- throw new IllegalArgumentException(sourceNs +
- ": no such name space");
- } catch (IOException x) {
- throw new IllegalArgumentException("source stale: "+x,x);
+ if (probe) {
+ try {
+ if (!source.isRegistered(handlerName)) {
+ InstanceNotFoundException infe =
+ new InstanceNotFoundException(handlerName);
+ throw new IllegalArgumentException(sourceNs +
+ ": no such name space", infe);
+ }
+ } catch (IOException x) {
+ throw new IllegalArgumentException("source stale: "+x,x);
+ }
}
}
this.source = source;
@@ -191,7 +190,6 @@ public abstract class RoutingProxy<T ext
JMXNamespaces.normalizeNamespaceName(targetNs));
this.router =
new ObjectNameRouter(this.targetNs,this.sourceNs);
- this.forwardsContext = forwardsContext;
if (LOG.isLoggable(Level.FINER))
LOG.finer("RoutingProxy for " + this.sourceNs + " created");
@@ -199,14 +197,6 @@ public abstract class RoutingProxy<T ext
@Override
public T source() { return source; }
-
- ObjectNameRouter getObjectNameRouter() {
-// TODO: uncomment this when contexts are added
-// if (forwardsContext)
-// return ObjectNameRouter.wrapWithContext(router);
-// else
- return router;
- }
@Override
public ObjectName toSource(ObjectName targetName)
@@ -222,8 +212,7 @@ public abstract class RoutingProxy<T ext
if (defaultDomain != null)
targetName = targetName.withDomain(defaultDomain);
}
- final ObjectNameRouter r = getObjectNameRouter();
- return r.toSourceContext(targetName,true);
+ return router.toSourceContext(targetName,true);
}
@Override
@@ -243,8 +232,7 @@ public abstract class RoutingProxy<T ext
public ObjectName toTarget(ObjectName sourceName)
throws MalformedObjectNameException {
if (sourceName == null) return null;
- final ObjectNameRouter r = getObjectNameRouter();
- return r.toTargetContext(sourceName,false);
+ return router.toTargetContext(sourceName,false);
}
private Object getAttributeFromHandler(String attributeName)
@@ -357,11 +345,8 @@ public abstract class RoutingProxy<T ext
// 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);
+ public R newInstance(
+ T source, String sourcePath, String targetPath, boolean probe);
}
// Performs a narrowDownToNamespace operation.
@@ -377,7 +362,7 @@ public abstract class RoutingProxy<T ext
static <T extends MBeanServerConnection, R extends RoutingProxy<T>>
R cd(Class<R> routingProxyClass,
RoutingProxyFactory<T,R> factory,
- T source, String sourcePath) {
+ T source, String sourcePath, boolean probe) {
if (source == null) throw new IllegalArgumentException("null");
if (source.getClass().equals(routingProxyClass)) {
// cast is OK here, but findbugs complains unless we use class.cast
@@ -400,14 +385,13 @@ public abstract class RoutingProxy<T ext
final String path =
JMXNamespaces.concat(other.getSourceNamespace(),
sourcePath);
- return factory.newInstance(other.source(),path,"",
- other.forwardsContext);
+ return factory.newInstance(other.source(), path, "", probe);
}
// 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);
+ return factory.newInstance(source, sourcePath, "", probe);
}
}
--- a/src/share/classes/com/sun/jmx/namespace/RoutingServerProxy.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/namespace/RoutingServerProxy.java Tue Nov 11 09:07:58 2008 +0000
@@ -54,7 +54,6 @@ import javax.management.QueryExp;
import javax.management.QueryExp;
import javax.management.ReflectionException;
import javax.management.loading.ClassLoaderRepository;
-import javax.management.namespace.JMXNamespaces;
/**
* A RoutingServerProxy is an MBeanServer proxy that proxies a
@@ -76,19 +75,11 @@ public class RoutingServerProxy
extends RoutingProxy<MBeanServer>
implements MBeanServer {
- /**
- * Creates a new instance of RoutingServerProxy
- */
- public RoutingServerProxy(MBeanServer source,
- String sourceNs) {
- this(source,sourceNs,"",false);
- }
-
public RoutingServerProxy(MBeanServer source,
String sourceNs,
String targetNs,
- boolean forwardsContext) {
- super(source,sourceNs,targetNs,forwardsContext);
+ boolean probe) {
+ super(source, sourceNs, targetNs, probe);
}
/**
@@ -571,20 +562,15 @@ public class 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);
+ String sourcePath, String targetPath, boolean probe) {
+ return new RoutingServerProxy(
+ source, sourcePath, targetPath, probe);
}
};
- public static MBeanServer cd(MBeanServer source, String sourcePath) {
+ public static MBeanServer cd(
+ MBeanServer source, String sourcePath, boolean probe) {
return RoutingProxy.cd(RoutingServerProxy.class, FACTORY,
- source, sourcePath);
+ source, sourcePath, probe);
}
}
--- a/src/share/classes/com/sun/jmx/remote/internal/ArrayNotificationBuffer.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/remote/internal/ArrayNotificationBuffer.java Tue Nov 11 09:07:58 2008 +0000
@@ -120,7 +120,7 @@ public class ArrayNotificationBuffer imp
private final Collection<ShareBuffer> sharers = new HashSet<ShareBuffer>(1);
public static NotificationBuffer getNotificationBuffer(
- MBeanServer mbs, Map env) {
+ MBeanServer mbs, Map<String, ?> env) {
if (env == null)
env = Collections.emptyMap();
--- a/src/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java Tue Nov 11 09:07:58 2008 +0000
@@ -54,7 +54,7 @@ import com.sun.jmx.remote.util.EnvHelp;
public abstract class ClientNotifForwarder {
- public ClientNotifForwarder(Map env) {
+ public ClientNotifForwarder(Map<String, ?> env) {
this(null, env);
}
@@ -113,7 +113,7 @@ public abstract class ClientNotifForward
private Thread thread;
}
- public ClientNotifForwarder(ClassLoader defaultClassLoader, Map env) {
+ public ClientNotifForwarder(ClassLoader defaultClassLoader, Map<String, ?> env) {
maxNotifications = EnvHelp.getMaxFetchNotifNumber(env);
timeout = EnvHelp.getFetchTimeout(env);
--- a/src/share/classes/com/sun/jmx/remote/internal/ProxyInputStream.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/remote/internal/ProxyInputStream.java Tue Nov 11 09:07:58 2008 +0000
@@ -36,7 +36,7 @@ import org.omg.CORBA.TypeCode;
import org.omg.CORBA.TypeCode;
import org.omg.CORBA.portable.BoxedValueHelper;
-@SuppressWarnings("deprecation")
+@SuppressWarnings({"deprecation", "rawtypes"})
public class ProxyInputStream extends org.omg.CORBA_2_3.portable.InputStream {
public ProxyInputStream(org.omg.CORBA.portable.InputStream in) {
this.in = in;
--- a/src/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java Tue Nov 11 09:07:58 2008 +0000
@@ -59,7 +59,7 @@ public class ServerNotifForwarder {
public ServerNotifForwarder(MBeanServer mbeanServer,
- Map env,
+ Map<String, ?> env,
NotificationBuffer notifBuffer,
String connectionId) {
this.mbeanServer = mbeanServer;
--- a/src/share/classes/com/sun/jmx/remote/internal/Unmarshal.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/remote/internal/Unmarshal.java Tue Nov 11 09:07:58 2008 +0000
@@ -29,6 +29,6 @@ import java.rmi.MarshalledObject;
import java.rmi.MarshalledObject;
public interface Unmarshal {
- public Object get(MarshalledObject mo)
+ public Object get(MarshalledObject<?> mo)
throws IOException, ClassNotFoundException;
}
--- a/src/share/classes/com/sun/jmx/remote/security/FileLoginModule.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/remote/security/FileLoginModule.java Tue Nov 11 09:07:58 2008 +0000
@@ -26,6 +26,7 @@ package com.sun.jmx.remote.security;
package com.sun.jmx.remote.security;
import com.sun.jmx.mbeanserver.GetPropertyAction;
+import com.sun.jmx.mbeanserver.Util;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
@@ -146,8 +147,8 @@ public class FileLoginModule implements
// Initial state
private Subject subject;
private CallbackHandler callbackHandler;
- private Map<String, ?> sharedState;
- private Map options;
+ private Map<String, Object> sharedState;
+ private Map<String, ?> options;
private String passwordFile;
private String passwordFileDisplayName;
private boolean userSuppliedPasswordFile;
@@ -172,7 +173,7 @@ public class FileLoginModule implements
this.subject = subject;
this.callbackHandler = callbackHandler;
- this.sharedState = sharedState;
+ this.sharedState = Util.cast(sharedState);
this.options = options;
// initialize any configured options
@@ -454,8 +455,8 @@ public class FileLoginModule implements
if (storePass &&
!sharedState.containsKey(USERNAME_KEY) &&
!sharedState.containsKey(PASSWORD_KEY)) {
- ((Map) sharedState).put(USERNAME_KEY, username);
- ((Map) sharedState).put(PASSWORD_KEY, password);
+ sharedState.put(USERNAME_KEY, username);
+ sharedState.put(PASSWORD_KEY, password);
}
// Create a new user principal
--- a/src/share/classes/com/sun/jmx/remote/security/JMXPluggableAuthenticator.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/remote/security/JMXPluggableAuthenticator.java Tue Nov 11 09:07:58 2008 +0000
@@ -87,7 +87,7 @@ public final class JMXPluggableAuthentic
* @exception SecurityException if the authentication mechanism cannot be
* initialized.
*/
- public JMXPluggableAuthenticator(Map env) {
+ public JMXPluggableAuthenticator(Map<?, ?> env) {
String loginConfigName = null;
String passwordFile = null;
--- a/src/share/classes/com/sun/jmx/remote/security/MBeanServerFileAccessController.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/remote/security/MBeanServerFileAccessController.java Tue Nov 11 09:07:58 2008 +0000
@@ -249,9 +249,8 @@ public class MBeanServerFileAccessContro
}
});
if (s == null) return; /* security has not been enabled */
- final Set principals = s.getPrincipals();
- for (Iterator i = principals.iterator(); i.hasNext(); ) {
- final Principal p = (Principal) i.next();
+ final Set<Principal> principals = s.getPrincipals();
+ for (Principal p : principals) {
String grantedAccessLevel;
synchronized (props) {
grantedAccessLevel = props.getProperty(p.getName());
@@ -271,8 +270,8 @@ public class MBeanServerFileAccessContro
}
private void checkValues(Properties props) {
- Collection c = props.values();
- for (Iterator i = c.iterator(); i.hasNext(); ) {
+ Collection<?> c = props.values();
+ for (Iterator<?> i = c.iterator(); i.hasNext(); ) {
final String accessLevel = (String) i.next();
if (!accessLevel.equals(READONLY) &&
!accessLevel.equals(READWRITE)) {
--- a/src/share/classes/com/sun/jmx/remote/util/ClassLoaderWithRepository.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/remote/util/ClassLoaderWithRepository.java Tue Nov 11 09:07:58 2008 +0000
@@ -38,7 +38,7 @@ public class ClassLoaderWithRepository e
this.cl2 = cl2;
}
- protected Class findClass(String name) throws ClassNotFoundException {
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
return repository.loadClass(name);
} catch (ClassNotFoundException cne) {
--- a/src/share/classes/com/sun/jmx/remote/util/ClassLogger.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/remote/util/ClassLogger.java Tue Nov 11 09:07:58 2008 +0000
@@ -41,7 +41,7 @@ public class ClassLogger {
people to use at least J2SE 1.4. */
boolean loaded = false;
try {
- Class c = java.util.logging.Logger.class;
+ Class<?> c = java.util.logging.Logger.class;
loaded = true;
} catch (Error e) {
// OK.
--- a/src/share/classes/com/sun/jmx/remote/util/EnvHelp.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/remote/util/EnvHelp.java Tue Nov 11 09:07:58 2008 +0000
@@ -117,7 +117,7 @@ public class EnvHelp {
* <code>jmx.remote.default.class.loader.name</code> is specified
* and the ClassLoader MBean is not found in <var>mbs</var>.
*/
- public static ClassLoader resolveServerClassLoader(Map env,
+ public static ClassLoader resolveServerClassLoader(Map<String, ?> env,
MBeanServer mbs)
throws InstanceNotFoundException {
@@ -194,7 +194,7 @@ public class EnvHelp {
* <code>jmx.remote.default.class.loader</code> is specified
* and is not an instance of {@link ClassLoader}.
*/
- public static ClassLoader resolveClientClassLoader(Map env) {
+ public static ClassLoader resolveClientClassLoader(Map<String, ?> env) {
if (env == null)
return Thread.currentThread().getContextClassLoader();
@@ -241,7 +241,7 @@ public class EnvHelp {
try {
java.lang.reflect.Method getCause =
- t.getClass().getMethod("getCause", (Class[]) null);
+ t.getClass().getMethod("getCause", (Class<?>[]) null);
ret = (Throwable)getCause.invoke(t, (Object[]) null);
} catch (Exception e) {
@@ -264,7 +264,7 @@ public class EnvHelp {
* Returns the size of a notification buffer for a connector server.
* The default value is 1000.
*/
- public static int getNotifBufferSize(Map env) {
+ public static int getNotifBufferSize(Map<String, ?> env) {
int defaultQueueSize = 1000; // default value
// keep it for the compability for the fix:
@@ -327,7 +327,7 @@ public class EnvHelp {
* Returns the maximum notification number which a client will
* fetch every time.
*/
- public static int getMaxFetchNotifNumber(Map env) {
+ public static int getMaxFetchNotifNumber(Map<String, ?> env) {
return (int) getIntegerAttribute(env, MAX_FETCH_NOTIFS, 1000, 1,
Integer.MAX_VALUE);
}
@@ -344,7 +344,7 @@ public class EnvHelp {
/**
* Returns the timeout for a client to fetch notifications.
*/
- public static long getFetchTimeout(Map env) {
+ public static long getFetchTimeout(Map<String, ?> env) {
return getIntegerAttribute(env, FETCH_TIMEOUT, 60000L, 0,
Long.MAX_VALUE);
}
@@ -361,7 +361,7 @@ public class EnvHelp {
"com.sun.jmx.remote.notification.access.controller";
public static NotificationAccessController getNotificationAccessController(
- Map env) {
+ Map<String, ?> env) {
return (env == null) ? null :
(NotificationAccessController) env.get(NOTIF_ACCESS_CONTROLLER);
}
@@ -378,7 +378,7 @@ public class EnvHelp {
* an entry for <code>name</code> but it does not meet the
* constraints above.
*/
- public static long getIntegerAttribute(Map env, String name,
+ public static long getIntegerAttribute(Map<String, ?> env, String name,
long defaultValue, long minValue,
long maxValue) {
final Object o;
@@ -421,9 +421,8 @@ public class EnvHelp {
/* Check that all attributes have a key that is a String.
Could make further checks, e.g. appropriate types for attributes. */
- public static void checkAttributes(Map attributes) {
- for (Iterator it = attributes.keySet().iterator(); it.hasNext(); ) {
- Object key = it.next();
+ public static void checkAttributes(Map<?, ?> attributes) {
+ for (Object key : attributes.keySet()) {
if (!(key instanceof String)) {
final String msg =
"Attributes contain key that is not a string: " + key;
@@ -455,7 +454,7 @@ public class EnvHelp {
logger.trace("purgeUnserializable", "starts");
ObjectOutputStream oos = null;
int i = 0;
- for (Iterator it = objects.iterator(); it.hasNext(); i++) {
+ for (Iterator<?> it = objects.iterator(); it.hasNext(); i++) {
Object v = it.next();
if (v == null || v instanceof String) {
@@ -564,18 +563,18 @@ public class EnvHelp {
guarantees that we will never call next() on the corresponding
iterator. */
String sentinelKey = map.lastKey() + "X";
- Iterator keyIterator = map.keySet().iterator();
- Iterator stringIterator = hiddenStrings.iterator();
- Iterator prefixIterator = hiddenPrefixes.iterator();
+ Iterator<String> keyIterator = map.keySet().iterator();
+ Iterator<String> stringIterator = hiddenStrings.iterator();
+ Iterator<String> prefixIterator = hiddenPrefixes.iterator();
String nextString;
if (stringIterator.hasNext())
- nextString = (String) stringIterator.next();
+ nextString = stringIterator.next();
else
nextString = sentinelKey;
String nextPrefix;
if (prefixIterator.hasNext())
- nextPrefix = (String) prefixIterator.next();
+ nextPrefix = prefixIterator.next();
else
nextPrefix = sentinelKey;
@@ -583,7 +582,7 @@ public class EnvHelp {
or prefix, remove it. */
keys:
while (keyIterator.hasNext()) {
- String key = (String) keyIterator.next();
+ String key = keyIterator.next();
/* Continue through string-match values until we find one
that is either greater than the current key, or equal
@@ -591,7 +590,7 @@ public class EnvHelp {
int cmp = +1;
while ((cmp = nextString.compareTo(key)) < 0) {
if (stringIterator.hasNext())
- nextString = (String) stringIterator.next();
+ nextString = stringIterator.next();
else
nextString = sentinelKey;
}
@@ -609,7 +608,7 @@ public class EnvHelp {
continue keys;
}
if (prefixIterator.hasNext())
- nextPrefix = (String) prefixIterator.next();
+ nextPrefix = prefixIterator.next();
else
nextPrefix = sentinelKey;
}
@@ -640,7 +639,7 @@ public class EnvHelp {
/**
* Returns the server side connection timeout.
*/
- public static long getServerConnectionTimeout(Map env) {
+ public static long getServerConnectionTimeout(Map<String, ?> env) {
return getIntegerAttribute(env, SERVER_CONNECTION_TIMEOUT, 120000L,
0, Long.MAX_VALUE);
}
@@ -656,7 +655,7 @@ public class EnvHelp {
/**
* Returns the client connection check period.
*/
- public static long getConnectionCheckPeriod(Map env) {
+ public static long getConnectionCheckPeriod(Map<String, ?> env) {
return getIntegerAttribute(env, CLIENT_CONNECTION_CHECK_PERIOD, 60000L,
0, Long.MAX_VALUE);
}
@@ -691,7 +690,7 @@ public class EnvHelp {
* to {@code String}.
*/
public static boolean computeBooleanFromString(
- Map env, String prop, boolean systemProperty) {
+ Map<String, ?> env, String prop, boolean systemProperty) {
if (env == null)
throw new IllegalArgumentException("env map cannot be null");
@@ -744,7 +743,8 @@ public class EnvHelp {
* to {@code String}.
*/
public static boolean computeBooleanFromString(
- Map env, String prop, boolean systemProperty, boolean defaultValue) {
+ Map<String, ?> env, String prop,
+ boolean systemProperty, boolean defaultValue) {
if (env == null)
throw new IllegalArgumentException("env map cannot be null");
@@ -774,7 +774,7 @@ public class EnvHelp {
public static <K, V> Hashtable<K, V> mapToHashtable(Map<K, V> map) {
HashMap<K, V> m = new HashMap<K, V>(map);
if (m.containsKey(null)) m.remove(null);
- for (Iterator i = m.values().iterator(); i.hasNext(); )
+ for (Iterator<?> i = m.values().iterator(); i.hasNext(); )
if (i.next() == null) i.remove();
return new Hashtable<K, V>(m);
}
@@ -783,7 +783,7 @@ public class EnvHelp {
* Returns true if the parameter JMXConnector.USE_EVENT_SERVICE is set to a
* String equals "true" by ignoring case in the map or in the System.
*/
- public static boolean eventServiceEnabled(Map env) {
+ public static boolean eventServiceEnabled(Map<String, ?> env) {
return computeBooleanFromString(env, JMXConnector.USE_EVENT_SERVICE, true);
}
@@ -793,7 +793,7 @@ public class EnvHelp {
* If the property DELEGATE_TO_EVENT_SERVICE is not set, returns
* a default value of "true".
*/
- public static boolean delegateToEventService(Map env) {
+ public static boolean delegateToEventService(Map<String, ?> env) {
return computeBooleanFromString(env,
JMXConnectorServer.DELEGATE_TO_EVENT_SERVICE, true, true);
}
--- a/src/share/classes/com/sun/jmx/remote/util/EventClientConnection.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/remote/util/EventClientConnection.java Tue Nov 11 09:07:58 2008 +0000
@@ -138,8 +138,8 @@ public class EventClientConnection imple
Class<T> interfaceClass, Callable<EventClient> eventClientFactory) {
final InvocationHandler handler =
new EventClientConnection(connection,eventClientFactory);
- final Class[] interfaces =
- new Class[] {interfaceClass, EventClientFactory.class};
+ final Class<?>[] interfaces =
+ new Class<?>[] {interfaceClass, EventClientFactory.class};
Object proxy =
Proxy.newProxyInstance(interfaceClass.getClassLoader(),
@@ -156,7 +156,7 @@ public class EventClientConnection imple
// add/remove notification listener are routed to the EventClient
if (methodName.equals("addNotificationListener")
|| methodName.equals("removeNotificationListener")) {
- final Class[] sig = method.getParameterTypes();
+ final Class<?>[] sig = method.getParameterTypes();
if (sig.length>1 &&
NotificationListener.class.isAssignableFrom(sig[1])) {
return invokeBroadcasterMethod(proxy,method,args);
@@ -164,7 +164,7 @@ public class EventClientConnection imple
}
// subscribe/unsubscribe are also routed to the EventClient.
- final Class clazz = method.getDeclaringClass();
+ final Class<?> clazz = method.getDeclaringClass();
if (clazz.equals(EventClientFactory.class)) {
return invokeEventClientSubscriberMethod(proxy,method,args);
}
@@ -319,7 +319,7 @@ public class EventClientConnection imple
return true;
if (methodName.equals("equals")
&& Arrays.equals(method.getParameterTypes(),
- new Class[] {Object.class})
+ new Class<?>[] {Object.class})
&& isLocal(proxy, method))
return true;
return false;
@@ -430,13 +430,11 @@ public class EventClientConnection imple
* The {@code EventClient} is created lazily, when it is needed
* for the first time. If null, a default factory will be used
* (see {@link #createEventClient}).
- * @return the
+ * @return the MBeanServerConnection.
**/
public static MBeanServerConnection getEventConnectionFor(
MBeanServerConnection connection,
Callable<EventClient> eventClientFactory) {
- // if c already uses an EventClient no need to create a new one.
- //
if (connection instanceof EventClientFactory
&& eventClientFactory != null)
throw new IllegalArgumentException("connection already uses EventClient");
--- a/src/share/classes/com/sun/jmx/remote/util/OrderClassLoaders.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/jmx/remote/util/OrderClassLoaders.java Tue Nov 11 09:07:58 2008 +0000
@@ -32,7 +32,7 @@ public class OrderClassLoaders extends C
this.cl2 = cl2;
}
- protected Class findClass(String name) throws ClassNotFoundException {
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
return super.findClass(name);
} catch (ClassNotFoundException cne) {
--- a/src/share/classes/com/sun/org/apache/xml/internal/security/utils/IdResolver.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/com/sun/org/apache/xml/internal/security/utils/IdResolver.java Tue Nov 11 09:07:58 2008 +0000
@@ -70,10 +70,13 @@ public class IdResolver {
*/
public static void registerElementById(Element element, String idValue) {
Document doc = element.getOwnerDocument();
- WeakHashMap elementMap = (WeakHashMap) docMap.get(doc);
- if(elementMap == null) {
- elementMap = new WeakHashMap();
- docMap.put(doc, elementMap);
+ WeakHashMap elementMap;
+ synchronized (docMap) {
+ elementMap = (WeakHashMap) docMap.get(doc);
+ if (elementMap == null) {
+ elementMap = new WeakHashMap();
+ docMap.put(doc, elementMap);
+ }
}
elementMap.put(idValue, new WeakReference(element));
}
@@ -153,7 +156,10 @@ public class IdResolver {
private static Element getElementByIdType(Document doc, String id) {
if (log.isLoggable(java.util.logging.Level.FINE))
log.log(java.util.logging.Level.FINE, "getElementByIdType() Search for ID " + id);
- WeakHashMap elementMap = (WeakHashMap) docMap.get(doc);
+ WeakHashMap elementMap;
+ synchronized (docMap) {
+ elementMap = (WeakHashMap) docMap.get(doc);
+ }
if (elementMap != null) {
WeakReference weakReference = (WeakReference) elementMap.get(id);
if (weakReference != null) {
--- a/src/share/classes/java/security/cert/CertPathValidatorException.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/java/security/cert/CertPathValidatorException.java Tue Nov 11 09:07:58 2008 +0000
@@ -113,7 +113,7 @@ public class CertPathValidatorException
* permitted, and indicates that the cause is nonexistent or unknown.)
*/
public CertPathValidatorException(Throwable cause) {
- this(null, cause);
+ this((cause == null ? null : cause.toString()), cause);
}
/**
--- a/src/share/classes/javax/management/AttributeList.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/AttributeList.java Tue Nov 11 09:07:58 2008 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2005 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1999-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,17 +27,23 @@ package javax.management;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
/**
- * Represents a list of values for attributes of an MBean. The methods
- * used for the insertion of {@link javax.management.Attribute
- * Attribute} objects in the <CODE>AttributeList</CODE> overrides the
- * corresponding methods in the superclass
- * <CODE>ArrayList</CODE>. This is needed in order to insure that the
- * objects contained in the <CODE>AttributeList</CODE> are only
- * <CODE>Attribute</CODE> objects. This avoids getting an exception
- * when retrieving elements from the <CODE>AttributeList</CODE>.
+ * <p>Represents a list of values for attributes of an MBean. See the
+ * {@link MBeanServerConnection#getAttributes getAttributes} and
+ * {@link MBeanServerConnection#setAttributes setAttributes} methods of
+ * {@link MBeanServer} and {@link MBeanServerConnection}.</p>
+ *
+ * <p id="type-safe">For compatibility reasons, it is possible, though
+ * highly discouraged, to add objects to an {@code AttributeList} that are
+ * not instances of {@code Attribute}. However, an {@code AttributeList}
+ * can be made <em>type-safe</em>, which means that an attempt to add
+ * an object that is not an {@code Attribute} will produce an {@code
+ * IllegalArgumentException}. An {@code AttributeList} becomes type-safe
+ * when the method {@link #asList()} is called on it.</p>
*
* @since 1.5
*/
@@ -58,8 +64,8 @@ import java.util.List;
*/
public class AttributeList extends ArrayList<Object> {
- private transient boolean typeSafe;
- private transient boolean tainted;
+ private transient volatile boolean typeSafe;
+ private transient volatile boolean tainted;
/* Serial version */
private static final long serialVersionUID = -4077085769279709076L;
@@ -124,11 +130,61 @@ public class AttributeList extends Array
// Check for non-Attribute objects
//
- checkTypeSafe(list);
+ adding(list);
// Build the List<Attribute>
//
super.addAll(list);
+ }
+
+ /**
+ * <p>Constructs an {@code AttributeList} containing the elements of
+ * the {@code Map} specified, in the order in which they appear in the
+ * {@code Map}'s {@link Map#entrySet entrySet}. For each <em>{@code
+ * key}</em> and <em>{@code value}</em> in the {@code Map}, the constructed
+ * {@code AttributeList} will contain {@link Attribute#Attribute
+ * Attribute(<em>key</em>, <em>value</em>)}.</p>
+ *
+ * @param map the {@code Map} defining the elements of the new
+ * {@code AttributeList}.
+ */
+ public AttributeList(Map<String, ?> map) {
+ for (Map.Entry<String, ?> entry : map.entrySet())
+ add(new Attribute(entry.getKey(), entry.getValue()));
+ typeSafe = true;
+ }
+
+ /**
+ * <p>Return a {@code Map} that is a snapshot of the values in this
+ * {@code AttributeList}. Each key in the {@code Map} is the {@linkplain
+ * Attribute#getName() name} of an {@code Attribute} in the list, and each
+ * value is the corresponding {@linkplain Attribute#getValue() value} of
+ * that {@code Attribute}. The {@code AttributeList} and the {@code Map}
+ * are unrelated after the call, that is, changes to one do not affect the
+ * other.</p>
+ *
+ * <p>If the {@code AttributeList} contains more than one {@code Attribute}
+ * with the same name, then the {@code Map} will contain an entry
+ * for that name where the value is that of the last of those {@code
+ * Attribute}s.</p>
+ *
+ * @return the new {@code Map}.
+ *
+ * @throws IllegalArgumentException if this {@code AttributeList} contains
+ * an element that is not an {@code Attribute}.
+ */
+ public Map<String, Object> toMap() {
+ Map<String, Object> map = new LinkedHashMap<String, Object>();
+
+ // We can't call adding(this) because we're not necessarily typeSafe
+ if (tainted)
+ throw new IllegalArgumentException("AttributeList contains non-Attribute");
+
+ for (Object x : this) {
+ Attribute a = (Attribute) x;
+ map.put(a.getName(), a.getValue());
+ }
+ return map;
}
/**
@@ -154,12 +210,10 @@ public class AttributeList extends Array
*/
@SuppressWarnings("unchecked")
public List<Attribute> asList() {
- if (!typeSafe) {
- if (tainted)
- checkTypeSafe(this);
- typeSafe = true;
- }
- return (List<Attribute>) (List) this;
+ typeSafe = true;
+ if (tainted)
+ adding((Collection<?>) this); // will throw IllegalArgumentException
+ return (List<Attribute>) (List<?>) this;
}
/**
@@ -175,7 +229,7 @@ public class AttributeList extends Array
* Inserts the attribute specified as an element at the position specified.
* Elements with an index greater than or equal to the current position are
* shifted up. If the index is out of range (index < 0 || index >
- * size() a RuntimeOperationsException should be raised, wrapping the
+ * size()) a RuntimeOperationsException should be raised, wrapping the
* java.lang.IndexOutOfBoundsException thrown.
*
* @param object The <CODE>Attribute</CODE> object to be inserted.
@@ -245,8 +299,7 @@ public class AttributeList extends Array
public boolean addAll(int index, AttributeList list) {
try {
return super.addAll(index, list);
- }
- catch (IndexOutOfBoundsException e) {
+ } catch (IndexOutOfBoundsException e) {
throw new RuntimeOperationsException(e,
"The specified index is out of range");
}
@@ -258,96 +311,77 @@ public class AttributeList extends Array
* been called on this instance.
*/
- @Override
- public boolean add(Object o) {
- if (!tainted)
- tainted = isTainted(o);
+ /**
+ * {@inheritDoc}
+ * @throws IllegalArgumentException if this {@code AttributeList} is
+ * <a href="#type-safe">type-safe</a> and {@code element} is not an
+ * {@code Attribute}.
+ */
+ @Override
+ public boolean add(Object element) {
+ adding(element);
+ return super.add(element);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @throws IllegalArgumentException if this {@code AttributeList} is
+ * <a href="#type-safe">type-safe</a> and {@code element} is not an
+ * {@code Attribute}.
+ */
+ @Override
+ public void add(int index, Object element) {
+ adding(element);
+ super.add(index, element);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @throws IllegalArgumentException if this {@code AttributeList} is
+ * <a href="#type-safe">type-safe</a> and {@code c} contains an
+ * element that is not an {@code Attribute}.
+ */
+ @Override
+ public boolean addAll(Collection<?> c) {
+ adding(c);
+ return super.addAll(c);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @throws IllegalArgumentException if this {@code AttributeList} is
+ * <a href="#type-safe">type-safe</a> and {@code c} contains an
+ * element that is not an {@code Attribute}.
+ */
+ @Override
+ public boolean addAll(int index, Collection<?> c) {
+ adding(c);
+ return super.addAll(index, c);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @throws IllegalArgumentException if this {@code AttributeList} is
+ * <a href="#type-safe">type-safe</a> and {@code element} is not an
+ * {@code Attribute}.
+ */
+ @Override
+ public Object set(int index, Object element) {
+ adding(element);
+ return super.set(index, element);
+ }
+
+ private void adding(Object x) {
+ if (x == null || x instanceof Attribute)
+ return;
if (typeSafe)
- checkTypeSafe(o);
- return super.add(o);
- }
-
- @Override
- public void add(int index, Object element) {
- if (!tainted)
- tainted = isTainted(element);
- if (typeSafe)
- checkTypeSafe(element);
- super.add(index, element);
- }
-
- @Override
- public boolean addAll(Collection<?> c) {
- if (!tainted)
- tainted = isTainted(c);
- if (typeSafe)
- checkTypeSafe(c);
- return super.addAll(c);
- }
-
- @Override
- public boolean addAll(int index, Collection<?> c) {
- if (!tainted)
- tainted = isTainted(c);
- if (typeSafe)
- checkTypeSafe(c);
- return super.addAll(index, c);
- }
-
- @Override
- public Object set(int index, Object element) {
- if (!tainted)
- tainted = isTainted(element);
- if (typeSafe)
- checkTypeSafe(element);
- return super.set(index, element);
- }
-
- /**
- * IllegalArgumentException if o is a non-Attribute object.
- */
- private static void checkTypeSafe(Object o) {
- try {
- o = (Attribute) o;
- } catch (ClassCastException e) {
- throw new IllegalArgumentException(e);
- }
- }
-
- /**
- * IllegalArgumentException if c contains any non-Attribute objects.
- */
- private static void checkTypeSafe(Collection<?> c) {
- try {
- Attribute a;
- for (Object o : c)
- a = (Attribute) o;
- } catch (ClassCastException e) {
- throw new IllegalArgumentException(e);
- }
- }
-
- /**
- * Returns true if o is a non-Attribute object.
- */
- private static boolean isTainted(Object o) {
- try {
- checkTypeSafe(o);
- } catch (IllegalArgumentException e) {
- return true;
- }
- return false;
- }
-
- /**
- * Returns true if c contains any non-Attribute objects.
- */
- private static boolean isTainted(Collection<?> c) {
- try {
- checkTypeSafe(c);
- } catch (IllegalArgumentException e) {
- return true;
- }
- return false;
+ throw new IllegalArgumentException("Not an Attribute: " + x);
+ else
+ tainted = true;
+ }
+
+ private void adding(Collection<?> c) {
+ for (Object x : c)
+ adding(x);
}
}
--- a/src/share/classes/javax/management/DefaultLoaderRepository.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/DefaultLoaderRepository.java Tue Nov 11 09:07:58 2008 +0000
@@ -62,7 +62,7 @@ public class DefaultLoaderRepository {
*
* @exception ClassNotFoundException The specified class could not be found.
*/
- public static Class loadClass(String className)
+ public static Class<?> loadClass(String className)
throws ClassNotFoundException {
return javax.management.loading.DefaultLoaderRepository.loadClass(className);
}
@@ -82,7 +82,7 @@ public class DefaultLoaderRepository {
*
* @exception ClassNotFoundException The specified class could not be found.
*/
- public static Class loadClassWithout(ClassLoader loader,String className)
+ public static Class<?> loadClassWithout(ClassLoader loader,String className)
throws ClassNotFoundException {
return javax.management.loading.DefaultLoaderRepository.loadClassWithout(loader, className);
}
--- a/src/share/classes/javax/management/Descriptor.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/Descriptor.java Tue Nov 11 09:07:58 2008 +0000
@@ -35,8 +35,8 @@ import java.io.Serializable;
// Javadoc imports:
import java.lang.management.MemoryUsage;
import java.util.Arrays;
+import java.util.Locale;
import java.util.ResourceBundle;
-
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.MXBeanMappingFactory;
import javax.management.openmbean.OpenMBeanAttributeInfoSupport;
@@ -101,7 +101,7 @@ import javax.management.openmbean.OpenTy
*
* <tr><th>Name</th><th>Type</th><th>Used in</th><th>Meaning</th></tr>
*
- * <tr><td><a name="defaultValue"><i>defaultValue</i></a><td>Object</td>
+ * <tr id="defaultValue"><td><i>defaultValue</i><td>Object</td>
* <td>MBeanAttributeInfo<br>MBeanParameterInfo</td>
*
* <td>Default value for an attribute or parameter. See
@@ -118,19 +118,22 @@ import javax.management.openmbean.OpenTy
* deprecation, for example {@code "1.3 Replaced by the Capacity
* attribute"}.</td>
*
- * <tr id="descriptionResourceBundleBaseName">
- * <td>descriptionResource<br>BundleBaseName</td><td>String</td><td>Any</td>
+ * <tr><td id="descriptionResourceBundleBaseName"><i>descriptionResource<br>
+ * BundleBaseName</i></td><td>String</td><td>Any</td>
*
* <td>The base name for the {@link ResourceBundle} in which the key given in
* the {@code descriptionResourceKey} field can be found, for example
- * {@code "com.example.myapp.MBeanResources"}.</td>
- *
- * <tr id="descriptionResourceKey">
- * <td>descriptionResourceKey</td><td>String</td><td>Any</td>
+ * {@code "com.example.myapp.MBeanResources"}. See
+ * {@link MBeanInfo#localizeDescriptions MBeanInfo.localizeDescriptions}.</td>
+ *
+ * <tr><td id="descriptionResourceKey"><i>descriptionResourceKey</i></td>
+ * <td>String</td><td>Any</td>
*
* <td>A resource key for the description of this element. In
* conjunction with the {@code descriptionResourceBundleBaseName},
- * this can be used to find a localized version of the description.</td>
+ * this can be used to find a localized version of the description.
+ * See {@link MBeanInfo#localizeDescriptions MBeanInfo.localizeDescriptions}.
+ * </td>
*
* <tr><td>enabled</td><td>String</td>
* <td>MBeanAttributeInfo<br>MBeanNotificationInfo<br>MBeanOperationInfo</td>
@@ -144,7 +147,7 @@ import javax.management.openmbean.OpenTy
* might be disabled if it cannot currently be emitted but could be in
* other circumstances.</td>
*
- * <tr><td><a name="immutableInfo"><i>immutableInfo</i></a><td>String</td>
+ * <tr id="immutableInfo"><td><i>immutableInfo</i><td>String</td>
* <td>MBeanInfo</td>
*
* <td>The string {@code "true"} or {@code "false"} according as this
@@ -153,9 +156,11 @@ import javax.management.openmbean.OpenTy
* the lifetime of the MBean. Hence, a client can read it once and
* cache the read value. When this field is false or absent, there is
* no such guarantee, although that does not mean that the MBeanInfo
- * will necessarily change.</td>
- *
- * <tr><td>infoTimeout</td><td>String<br>Long</td><td>MBeanInfo</td>
+ * will necessarily change. See also the <a
+ * href="MBeanInfo.html#info-changed">{@code "jmx.mbean.info.changed"}</a>
+ * notification.</td>
+ *
+ * <tr id="infoTimeout"><td>infoTimeout</td><td>String<br>Long</td><td>MBeanInfo</td>
*
* <td>The time in milli-seconds that the MBeanInfo can reasonably be
* expected to be unchanged. The value can be a {@code Long} or a
@@ -164,9 +169,11 @@ import javax.management.openmbean.OpenTy
* that the MBeanInfo is not likely to change within this period and
* therefore can be cached. When this field is missing or has the
* value zero, it is not recommended to cache the MBeanInfo unless it
- * has the {@code immutableInfo} set to {@code true}.</td></tr>
- *
- * <tr><td><a name="interfaceClassName"><i>interfaceClassName</i></a></td>
+ * has the {@code immutableInfo} set to {@code true} or it has <a
+ * href="MBeanInfo.html#info-changed">{@code "jmx.mbean.info.changed"}</a> in
+ * its {@link MBeanNotificationInfo} array.</td></tr>
+ *
+ * <tr id="interfaceClassName"><td><i>interfaceClassName</i></td>
* <td>String</td><td>MBeanInfo</td>
*
* <td>The Java interface name for a Standard MBean or MXBean, as
@@ -175,19 +182,26 @@ import javax.management.openmbean.OpenTy
* StandardMBean} class will have this field in its MBeanInfo
* Descriptor.</td>
*
- * <tr><td><a name="legalValues"><i>legalValues</i></a></td>
+ * <tr id="legalValues"><td><i>legalValues</i></td>
* <td>{@literal Set<?>}</td><td>MBeanAttributeInfo<br>MBeanParameterInfo</td>
*
* <td>Legal values for an attribute or parameter. See
* {@link javax.management.openmbean}.</td>
*
- * <tr><td><a name="maxValue"><i>maxValue</i></a><td>Object</td>
+ * <tr id="locale"><td><i>locale</i></td>
+ * <td>String</td><td>Any</td>
+ *
+ * <td>The {@linkplain Locale locale} of the description in this
+ * {@code MBeanInfo}, {@code MBeanAttributeInfo}, etc, as returned
+ * by {@link Locale#toString()}.</td>
+ *
+ * <tr id="maxValue"><td><i>maxValue</i><td>Object</td>
* <td>MBeanAttributeInfo<br>MBeanParameterInfo</td>
*
* <td>Maximum legal value for an attribute or parameter. See
* {@link javax.management.openmbean}.</td>
*
- * <tr><td><a name="metricType">metricType</a><td>String</td>
+ * <tr id="metricType"><td>metricType</td><td>String</td>
* <td>MBeanAttributeInfo<br>MBeanOperationInfo</td>
*
* <td>The type of a metric, one of the strings "counter" or "gauge".
@@ -200,13 +214,13 @@ import javax.management.openmbean.OpenTy
* that can increase or decrease. Examples might be the number of
* open connections or a cache hit rate or a temperature reading.
*
- * <tr><td><a name="minValue"><i>minValue</i></a><td>Object</td>
+ * <tr id="minValue"><td><i>minValue</i><td>Object</td>
* <td>MBeanAttributeInfo<br>MBeanParameterInfo</td>
*
* <td>Minimum legal value for an attribute or parameter. See
* {@link javax.management.openmbean}.</td>
*
- * <tr><td><a name="mxbean"><i>mxbean</i></a><td>String</td>
+ * <tr id="mxbean"><td><i>mxbean</i><td>String</td>
* <td>MBeanInfo</td>
*
* <td>The string {@code "true"} or {@code "false"} according as this
@@ -223,7 +237,7 @@ import javax.management.openmbean.OpenTy
* MXBean, if it was not the {@linkplain MXBeanMappingFactory#DEFAULT default}
* one.</td>
*
- * <tr><td><a name="openType"><i>openType</i></a><td>{@link OpenType}</td>
+ * <tr id="openType"><td><i>openType</i><td>{@link OpenType}</td>
* <td>MBeanAttributeInfo<br>MBeanOperationInfo<br>MBeanParameterInfo</td>
*
* <td><p>The Open Type of this element. In the case of {@code
@@ -240,7 +254,7 @@ import javax.management.openmbean.OpenTy
* which case it indicates the Open Type that the {@link
* Notification#getUserData() user data} will have.</td>
*
- * <tr><td><a name="originalType"><i>originalType</i></a><td>String</td>
+ * <tr id="originalType"><td><i>originalType</i><td>String</td>
* <td>MBeanAttributeInfo<br>MBeanOperationInfo<br>MBeanParameterInfo</td>
*
* <td><p>The original Java type of this element as it appeared in the
@@ -282,11 +296,132 @@ import javax.management.openmbean.OpenTy
*
* </table>
*
- * <p>Some additional fields are defined by Model MBeans. See
- * {@link javax.management.modelmbean.ModelMBeanInfo ModelMBeanInfo}
- * and related classes and the chapter "Model MBeans" of the
- * <a href="http://java.sun.com/products/JavaManagement/download.html">
- * JMX Specification</a>.</p>
+ * <p>Some additional fields are defined by Model MBeans. See the
+ * information for <a href="modelmbean/ModelMBeanInfo.html#descriptor"><!--
+ * -->{@code ModelMBeanInfo}</a>,
+ * <a href="modelmbean/ModelMBeanAttributeInfo.html#descriptor"><!--
+ * -->{@code ModelMBeanAttributeInfo}</a>,
+ * <a href="modelmbean/ModelMBeanConstructorInfo.html#descriptor"><!--
+ * -->{@code ModelMBeanConstructorInfo}</a>,
+ * <a href="modelmbean/ModelMBeanNotificationInfo.html#descriptor"><!--
+ * -->{@code ModelMBeanNotificationInfo}</a>, and
+ * <a href="modelmbean/ModelMBeanOperationInfo.html#descriptor"><!--
+ * -->{@code ModelMBeanOperationInfo}</a>, as
+ * well as the chapter "Model MBeans" of the <a
+ * href="http://java.sun.com/products/JavaManagement/download.html">JMX
+ * Specification</a>. The following table summarizes these fields. Note
+ * that when the Type in this table is Number, a String that is the decimal
+ * representation of a Long can also be used.</p>
+ *
+ * <p>Nothing prevents the use of these fields in MBeans that are not Model
+ * MBeans. The <a href="#displayName">displayName</a>, <a href="#severity"><!--
+ * -->severity</a>, and <a href="#visibility">visibility</a> fields are of
+ * interest outside Model MBeans, for example. But only Model MBeans have
+ * a predefined behavior for these fields.</p>
+ *
+ * <table border="1" cellpadding="5">
+ *
+ * <tr><th>Name</th><th>Type</th><th>Used in</th><th>Meaning</th></tr>
+ *
+ * <tr><td>class</td><td>String</td><td>ModelMBeanOperationInfo</td>
+ * <td>Class where method is defined (fully qualified).</td></tr>
+ *
+ * <tr><td>currencyTimeLimit</td><td>Number</td>
+ * <td>ModelMBeanInfo<br>ModelMBeanAttributeInfo<br>ModelMBeanOperationInfo</td>
+ * <td>How long cached value is valid: <0 never, =0 always,
+ * >0 seconds.</td></tr>
+ *
+ * <tr><td>default</td><td>Object</td><td>ModelMBeanAttributeInfo</td>
+ * <td>Default value for attribute.</td></tr>
+ *
+ * <tr><td>descriptorType</td><td>String</td><td>Any</td>
+ * <td>Type of descriptor, "mbean", "attribute", "constructor", "operation",
+ * or "notification".</td></tr>
+ *
+ * <tr id="displayName"><td>displayName</td><td>String</td><td>Any</td>
+ * <td>Human readable name of this item.</td></tr>
+ *
+ * <tr><td>export</td><td>String</td><td>ModelMBeanInfo</td>
+ * <td>Name to be used to export/expose this MBean so that it is
+ * findable by other JMX Agents.</td></tr>
+ *
+ * <tr><td>getMethod</td><td>String</td><td>ModelMBeanAttributeInfo</td>
+ * <td>Name of operation descriptor for get method.</td></tr>
+ *
+ * <tr><td>lastUpdatedTimeStamp</td><td>Number</td>
+ * <td>ModelMBeanAttributeInfo<br>ModelMBeanOperationInfo</td>
+ * <td>When <a href="#value-field">value</a> was set.</td></tr>
+ *
+ * <tr><td>log</td><td>String</td><td>ModelMBeanInfo<br>ModelMBeanNotificationInfo</td>
+ * <td>t or T: log all notifications, f or F: log no notifications.</td></tr>
+ *
+ * <tr><td>logFile</td><td>String</td><td>ModelMBeanInfo<br>ModelMBeanNotificationInfo</td>
+ * <td>Fully qualified filename to log events to.</td></tr>
+ *
+ * <tr><td>messageID</td><td>String</td><td>ModelMBeanNotificationInfo</td>
+ * <td>Unique key for message text (to allow translation, analysis).</td></tr>
+ *
+ * <tr><td>messageText</td><td>String</td><td>ModelMBeanNotificationInfo</td>
+ * <td>Text of notification.</td></tr>
+ *
+ * <tr><td>name</td><td>String</td><td>Any</td>
+ * <td>Name of this item.</td></tr>
+ *
+ * <tr><td>persistFile</td><td>String</td><td>ModelMBeanInfo</td>
+ * <td>File name into which the MBean should be persisted.</td></tr>
+ *
+ * <tr><td>persistLocation</td><td>String</td><td>ModelMBeanInfo</td>
+ * <td>The fully qualified directory name where the MBean should be
+ * persisted (if appropriate).</td></tr>
+ *
+ * <tr><td>persistPeriod</td><td>Number</td>
+ * <td>ModelMBeanInfo<br>ModelMBeanAttributeInfo</td>
+ * <td>Frequency of persist cycle in seconds. Used when persistPolicy is
+ * "OnTimer" or "NoMoreOftenThan".</td></tr>
+ *
+ * <tr><td>persistPolicy</td><td>String</td>
+ * <td>ModelMBeanInfo<br>ModelMBeanAttributeInfo</td>
+ * <td>One of: OnUpdate|OnTimer|NoMoreOftenThan|OnUnregister|Always|Never.
+ * See the section "MBean Descriptor Fields" in the JMX specification
+ * document.</td></tr>
+ *
+ * <tr><td>presentationString</td><td>String</td><td>Any</td>
+ * <td>XML formatted string to allow presentation of data.</td></tr>
+ *
+ * <tr><td>protocolMap</td><td>Descriptor</td><td>ModelMBeanAttributeInfo</td>
+ * <td>See the section "Protocol Map Support" in the JMX specification
+ * document. Mappings must be appropriate for the attribute and entries
+ * can be updated or augmented at runtime.</td></tr>
+ *
+ * <tr><td>role</td><td>String</td>
+ * <td>ModelMBeanConstructorInfo<br>ModelMBeanOperationInfo</td>
+ * <td>One of "constructor", "operation", "getter", or "setter".</td></tr>
+ *
+ * <tr><td>setMethod</td><td>String</td><td>ModelMBeanAttributeInfo</td>
+ * <td>Name of operation descriptor for set method.</td></tr>
+ *
+ * <tr id="severity"><td>severity</td><td>Number</td>
+ * <td>ModelMBeanNotificationInfo</td>
+ * <td>0-6 where 0: unknown; 1: non-recoverable;
+ * 2: critical, failure; 3: major, severe;
+ * 4: minor, marginal, error; 5: warning;
+ * 6: normal, cleared, informative</td></tr>
+ *
+ * <tr><td>targetObject</td><td>Object</td><td>ModelMBeanOperationInfo</td>
+ * <td>Object on which to execute this method.</td></tr>
+ *
+ * <tr><td>targetType</td><td>String</td><td>ModelMBeanOperationInfo</td>
+ * <td>type of object reference for targetObject. Can be:
+ * ObjectReference | Handle | EJBHandle | IOR | RMIReference.</td></tr>
+ *
+ * <tr id="value-field"><td>value</td><td>Object</td>
+ * <td>ModelMBeanAttributeInfo<br>ModelMBeanOperationInfo</td>
+ * <td>Current (cached) value for attribute or operation.</td></tr>
+ *
+ * <tr id="visibility"><td>visibility</td><td>Number</td><td>Any</td>
+ * <td>1-4 where 1: always visible, 4: rarely visible.</td></tr>
+ *
+ * </table>
*
* @since 1.5
*/
@@ -439,7 +574,7 @@ public interface Descriptor extends Seri
public boolean isValid() throws RuntimeOperationsException;
/**
- * Compares this descriptor to the given object. The objects are equal if
+ * <p>Compares this descriptor to the given object. The objects are equal if
* the given object is also a Descriptor, and if the two Descriptors have
* the same field names (possibly differing in case) and the same
* associated values. The respective values for a field in the two
--- a/src/share/classes/javax/management/JMRuntimeException.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/JMRuntimeException.java Tue Nov 11 09:07:58 2008 +0000
@@ -70,7 +70,7 @@ public class JMRuntimeException extends
try {
java.lang.reflect.Method initCause =
Throwable.class.getMethod("initCause",
- new Class[] {Throwable.class});
+ new Class<?>[] {Throwable.class});
initCause.invoke(this, new Object[] {cause});
} catch (Exception e) {
// OK: just means we won't have debugging info
--- a/src/share/classes/javax/management/JMX.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/JMX.java Tue Nov 11 09:07:58 2008 +0000
@@ -30,6 +30,7 @@ import com.sun.jmx.remote.util.ClassLogg
import com.sun.jmx.remote.util.ClassLogger;
import java.beans.BeanInfo;
import java.beans.PropertyDescriptor;
+import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
@@ -37,6 +38,7 @@ import java.lang.reflect.Proxy;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.TreeMap;
+import javax.management.namespace.JMXNamespaces;
import javax.management.openmbean.MXBeanMappingFactory;
/**
@@ -60,6 +62,21 @@ public class JMX {
*/
public static final String DEFAULT_VALUE_FIELD = "defaultValue";
+ /**
+ * The name of the <a
+ * href="Descriptor.html#descriptionResourceBundleBaseName">{@code
+ * descriptionResourceBundleBaseName}</a> field.
+ */
+ public static final String DESCRIPTION_RESOURCE_BUNDLE_BASE_NAME_FIELD =
+ "descriptionResourceBundleBaseName";
+
+ /**
+ * The name of the <a href="Descriptor.html#descriptionResourceKey">{@code
+ * descriptionResourceKey}</a> field.
+ */
+ public static final String DESCRIPTION_RESOURCE_KEY_FIELD =
+ "descriptionResourceKey";
+
/**
* The name of the <a href="Descriptor.html#immutableInfo">{@code
* immutableInfo}</a> field.
@@ -77,6 +94,12 @@ public class JMX {
* legalValues}</a> field.
*/
public static final String LEGAL_VALUES_FIELD = "legalValues";
+
+ /**
+ * The name of the <a href="Descriptor.html#locale">{@code locale}</a>
+ * field.
+ */
+ public static final String LOCALE_FIELD = "locale";
/**
* The name of the <a href="Descriptor.html#maxValue">{@code
@@ -120,13 +143,12 @@ public class JMX {
* <p>Options to apply to an MBean proxy or to an instance of {@link
* StandardMBean}.</p>
*
- * <p>For example, to specify a custom {@link MXBeanMappingFactory}
- * for a {@code StandardMBean}, you might write this:</p>
+ * <p>For example, to specify the "wrapped object visible" option for a
+ * {@code StandardMBean}, you might write this:</p>
*
* <pre>
- * MXBeanMappingFactory factory = new MyMXBeanMappingFactory();
- * JMX.MBeanOptions opts = new JMX.MBeanOptions();
- * opts.setMXBeanMappingFactory(factory);
+ * StandardMBean.Options opts = new StandardMBean.Options();
+ * opts.setWrappedObjectVisible(true);
* StandardMBean mbean = new StandardMBean(impl, intf, opts);
* </pre>
*
@@ -463,6 +485,12 @@ public class JMX {
* likewise for the other methods of {@link
* NotificationBroadcaster} and {@link NotificationEmitter}.</p>
*
+ * <p>This method is equivalent to {@link
+ * #newMBeanProxy(MBeanServerConnection, ObjectName, Class, JMX.MBeanOptions)
+ * newMBeanProxy(connection, objectName, interfaceClass, opts)}, where
+ * {@code opts} is a {@link JMX.ProxyOptions} representing the
+ * {@code notificationEmitter} parameter.</p>
+ *
* @param connection the MBean server to forward to.
* @param objectName the name of the MBean within
* {@code connection} to forward to.
@@ -554,10 +582,6 @@ public class JMX {
* MemoryUsage} using the MXBean mapping rules.</p>
*
* </ul>
- *
- * <p>The object returned by this method is a
- * {@link Proxy} whose {@code InvocationHandler} is an
- * {@link MBeanServerInvocationHandler}.</p>
*
* <p>This method is equivalent to {@link
* #newMXBeanProxy(MBeanServerConnection, ObjectName, Class,
@@ -601,6 +625,17 @@ public class JMX {
* likewise for the other methods of {@link
* NotificationBroadcaster} and {@link NotificationEmitter}.</p>
*
+ * <p>This method is equivalent to {@link
+ * #newMBeanProxy(MBeanServerConnection, ObjectName, Class, JMX.MBeanOptions)
+ * newMBeanProxy(connection, objectName, interfaceClass, opts)}, where
+ * {@code opts} is a {@link JMX.ProxyOptions} where the {@link
+ * JMX.ProxyOptions#getMXBeanMappingFactory() MXBeanMappingFactory}
+ * property is
+ * {@link MXBeanMappingFactory#forInterface(Class)
+ * MXBeanMappingFactory.forInterface(interfaceClass)} and the {@link
+ * JMX.ProxyOptions#isNotificationEmitter() notificationEmitter} property
+ * is equal to the {@code notificationEmitter} parameter.</p>
+ *
* @param connection the MBean server to forward to.
* @param objectName the name of the MBean within
* {@code connection} to forward to.
@@ -655,6 +690,36 @@ public class JMX {
* arbitrary Java types and Open Types.</li>
* </ul>
*
+ * <p>The object returned by this method is a
+ * {@link Proxy} whose {@code InvocationHandler} is an
+ * {@link MBeanServerInvocationHandler}. This means that it is possible
+ * to retrieve the parameters that were used to produce the proxy. If the
+ * proxy was produced as follows...</p>
+ *
+ * <pre>
+ * FooMBean proxy =
+ * JMX.newMBeanProxy(connection, objectName, FooMBean.class, opts);
+ * </pre>
+ *
+ * <p>...then you can get the {@code MBeanServerInvocationHandler} like
+ * this...</p>
+ *
+ * <pre>
+ * MBeanServerInvocationHandler mbsih = (MBeanServerInvocationHandler)
+ * {@link Proxy#getInvocationHandler(Object)
+ * Proxy.getInvocationHandler}(proxy);
+ * </pre>
+ *
+ * <p>...and you can retrieve {@code connection}, {@code
+ * objectName}, and {@code opts} using the {@link
+ * MBeanServerInvocationHandler#getMBeanServerConnection()
+ * getMBeanServerConnection()}, {@link
+ * MBeanServerInvocationHandler#getObjectName() getObjectName()}, and
+ * {@link MBeanServerInvocationHandler#getMBeanOptions() getMBeanOptions()}
+ * methods on {@code mbsih}. You can retrieve {@code FooMBean.class}
+ * using {@code proxy.getClass().}{@link
+ * Class#getInterfaces() getInterfaces()}.</p>
+ *
* @param connection the MBean server to forward to.
* @param objectName the name of the MBean within
* {@code connection} to forward to.
@@ -703,12 +768,12 @@ public class JMX {
InvocationHandler handler = new MBeanServerInvocationHandler(
connection, objectName, opts);
- final Class[] interfaces;
+ final Class<?>[] interfaces;
if (notificationEmitter) {
interfaces =
new Class<?>[] {interfaceClass, NotificationEmitter.class};
} else
- interfaces = new Class[] {interfaceClass};
+ interfaces = new Class<?>[] {interfaceClass};
Object proxy = Proxy.newProxyInstance(
interfaceClass.getClassLoader(),
interfaces,
@@ -765,4 +830,80 @@ public class JMX {
((DynamicWrapperMBean) mbean).getWrappedObject() : mbean;
return (MBeanInjector.injectsSendNotification(resource));
}
+
+ /**
+ * <p>Return the version of the JMX specification that a (possibly remote)
+ * MBean Server is using. The JMX specification described in this
+ * documentation is version 2.0. The earlier versions that might be
+ * reported by this method are 1.0, 1.1, 1.2, and 1.4. (There is no 1.3.)
+ * All of these versions and all future versions can be compared using
+ * {@link String#compareTo(String)}. So, for example, to tell if
+ * {@code mbsc} is running at least version 2.0 you can write:</p>
+ *
+ * <pre>
+ * String version = JMX.getSpecificationVersion(mbsc, null);
+ * boolean atLeast2dot0 = (version.compareTo("2.0") >= 0);
+ * </pre>
+ *
+ * <p>A remote MBean Server might be running an earlier version of the
+ * JMX API, and in that case <a href="package-summary.html#interop">certain
+ * features</a> might not be available in it.</p>
+ *
+ * <p>The version of the MBean Server {@code mbsc} is not necessarily
+ * the version of all namespaces within that MBean Server, for example
+ * if some of them use {@link javax.management.namespace.JMXRemoteNamespace
+ * JMXRemoteNamespace}. To determine the version of the namespace
+ * that a particular MBean is in, give its name as the {@code mbeanName}
+ * parameter.</p>
+ *
+ * @param mbsc a connection to an MBean Server.
+ *
+ * @param mbeanName the name of an MBean within that MBean Server, or null.
+ * If non-null, the namespace of this name, as determined by
+ * {@link JMXNamespaces#getContainingNamespace
+ * JMXNamespaces.getContainingNamespace}, is the one whose specification
+ * version will be returned.
+ *
+ * @return the JMX specification version reported by that MBean Server.
+ *
+ * @throws IllegalArgumentException if {@code mbsc} is null, or if
+ * {@code mbeanName} includes a wildcard character ({@code *} or {@code ?})
+ * in its namespace.
+ *
+ * @throws IOException if the version cannot be obtained, either because
+ * there is a communication problem or because the remote MBean Server
+ * does not have the appropriate {@linkplain
+ * MBeanServerDelegateMBean#getSpecificationVersion() attribute}.
+ *
+ * @see <a href="package-summary.html#interop">Interoperability between
+ * versions of the JMX specification</a>
+ * @see MBeanServerDelegateMBean#getSpecificationVersion
+ */
+ public static String getSpecificationVersion(
+ MBeanServerConnection mbsc, ObjectName mbeanName)
+ throws IOException {
+ if (mbsc == null)
+ throw new IllegalArgumentException("Null MBeanServerConnection");
+
+ String namespace;
+ if (mbeanName == null)
+ namespace = "";
+ else
+ namespace = JMXNamespaces.getContainingNamespace(mbeanName);
+ if (namespace.contains("*") || namespace.contains("?")) {
+ throw new IllegalArgumentException(
+ "ObjectName contains namespace wildcard: " + mbeanName);
+ }
+
+ try {
+ if (namespace.length() > 0)
+ mbsc = JMXNamespaces.narrowToNamespace(mbsc, namespace);
+ return (String) mbsc.getAttribute(
+ MBeanServerDelegate.DELEGATE_NAME, "SpecificationVersion");
+ } catch (IOException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new IOException(e);
+ }
+ }
}
--- a/src/share/classes/javax/management/MBeanAttributeInfo.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/MBeanAttributeInfo.java Tue Nov 11 09:07:58 2008 +0000
@@ -316,7 +316,7 @@ public class MBeanAttributeInfo extends
*/
private static String attributeType(Method getter, Method setter)
throws IntrospectionException {
- Class type = null;
+ Class<?> type = null;
if (getter != null) {
if (getter.getParameterTypes().length != 0) {
@@ -330,7 +330,7 @@ public class MBeanAttributeInfo extends
}
if (setter != null) {
- Class params[] = setter.getParameterTypes();
+ Class<?> params[] = setter.getParameterTypes();
if (params.length != 1) {
throw new IntrospectionException("bad setter arg count");
}
--- a/src/share/classes/javax/management/MBeanConstructorInfo.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/MBeanConstructorInfo.java Tue Nov 11 09:07:58 2008 +0000
@@ -64,7 +64,7 @@ public class MBeanConstructorInfo extend
* @param constructor The <CODE>java.lang.reflect.Constructor</CODE>
* object describing the MBean constructor.
*/
- public MBeanConstructorInfo(String description, Constructor constructor) {
+ public MBeanConstructorInfo(String description, Constructor<?> constructor) {
this(constructor.getName(), description,
constructorSignature(constructor),
Introspector.descriptorForElement(constructor));
@@ -210,8 +210,8 @@ public class MBeanConstructorInfo extend
return hash;
}
- private static MBeanParameterInfo[] constructorSignature(Constructor cn) {
- final Class[] classes = cn.getParameterTypes();
+ private static MBeanParameterInfo[] constructorSignature(Constructor<?> cn) {
+ final Class<?>[] classes = cn.getParameterTypes();
final Annotation[][] annots = cn.getParameterAnnotations();
return MBeanOperationInfo.parameters(classes, annots);
}
--- a/src/share/classes/javax/management/MBeanInfo.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/MBeanInfo.java Tue Nov 11 09:07:58 2008 +0000
@@ -25,6 +25,7 @@
package javax.management;
+import com.sun.jmx.mbeanserver.Util;
import java.io.IOException;
import java.io.StreamCorruptedException;
import java.io.Serializable;
@@ -37,6 +38,12 @@ import java.security.AccessController;
import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import static javax.management.ImmutableDescriptor.nonNullDescriptor;
/**
@@ -45,6 +52,17 @@ import static javax.management.Immutable
* management operations. Instances of this class are immutable.
* Subclasses may be mutable but this is not recommended.</p>
*
+ * <p id="info-changed">Usually the {@code MBeanInfo} for any given MBean does
+ * not change over the lifetime of that MBean. Dynamic MBeans can change their
+ * {@code MBeanInfo} and in that case it is recommended that they emit a {@link
+ * Notification} with a {@linkplain Notification#getType() type} of {@code
+ * "jmx.mbean.info.changed"} and a {@linkplain Notification#getUserData()
+ * userData} that is the new {@code MBeanInfo}. This is not required, but
+ * provides a conventional way for clients of the MBean to discover the change.
+ * See also the <a href="Descriptor.html#immutableInfo">immutableInfo</a> and
+ * <a href="Descriptor.html#infoTimeout">infoTimeout</a> fields in the {@code
+ * MBeanInfo} {@link Descriptor}.</p>
+ *
* <p>The contents of the <code>MBeanInfo</code> for a Dynamic MBean
* are determined by its {@link DynamicMBean#getMBeanInfo
* getMBeanInfo()} method. This includes Open MBeans and Model
@@ -62,27 +80,49 @@ import static javax.management.Immutable
* constructors in that object;
*
* <li>{@link #getAttributes()} returns the list of all attributes
- * whose existence is deduced from the presence in the MBean interface
- * of a <code>get<i>Name</i></code>, <code>is<i>Name</i></code>, or
- * <code>set<i>Name</i></code> method that conforms to the conventions
+ * whose existence is deduced as follows:
+ * <ul>
+ * <li>if the Standard MBean is defined with an MBean interface,
+ * from <code>get<i>Name</i></code>, <code>is<i>Name</i></code>, or
+ * <code>set<i>Name</i></code> methods that conform to the conventions
* for Standard MBeans;
- *
- * <li>{@link #getOperations()} returns the list of all methods in
+ * <li>if the Standard MBean is defined with the {@link MBean @MBean} or
+ * {@link MXBean @MXBean} annotation on a class, from methods with the
+ * {@link ManagedAttribute @ManagedAttribute} annotation;
+ * </ul>
+ *
+ * <li>{@link #getOperations()} returns the list of all operations whose
+ * existence is deduced as follows:
+ * <ul>
+ * <li>if the Standard MBean is defined with an MBean interface, from methods in
* the MBean interface that do not represent attributes;
- *
- * <li>{@link #getNotifications()} returns an empty array if the MBean
- * does not implement the {@link NotificationBroadcaster} interface,
- * otherwise the result of calling {@link
+ * <li>if the Standard MBean is defined with the {@link MBean @MBean} or
+ * {@link MXBean @MXBean} annotation on a class, from methods with the
+ * {@link ManagedOperation @ManagedOperation} annotation;
+ * </ul>
+ *
+ * <li>{@link #getNotifications()} returns:
+ * <ul>
+ * <li>if the MBean implements the {@link NotificationBroadcaster} interface,
+ * the result of calling {@link
* NotificationBroadcaster#getNotificationInfo()} on it;
+ * <li>otherwise, if there is a {@link NotificationInfo @NotificationInfo}
+ * or {@link NotificationInfos @NotificationInfos} annotation on the
+ * MBean interface or <code>@MBean</code> or <code>@MXBean</code>
+ * class, the array implied by those annotations;
+ * <li>otherwise an empty array;
+ * </ul>
*
* <li>{@link #getDescriptor()} returns a descriptor containing the contents
- * of any descriptor annotations in the MBean interface.
+ * of any descriptor annotations in the MBean interface (see
+ * {@link DescriptorFields @DescriptorFields} and
+ * {@link DescriptorKey @DescriptorKey}).
*
* </ul>
*
* <p>The description returned by {@link #getDescription()} and the
* descriptions of the contained attributes and operations are determined
- * by the corresponding <!-- link here --> Description annotations if any;
+ * by the corresponding {@link Description} annotations if any;
* otherwise their contents are not specified.</p>
*
* <p>The remaining details of the <code>MBeanInfo</code> for a
@@ -257,6 +297,7 @@ public class MBeanInfo implements Clonea
* <p>Since this class is immutable, the clone method is chiefly of
* interest to subclasses.</p>
*/
+ @Override
public Object clone () {
try {
return super.clone() ;
@@ -441,6 +482,7 @@ public class MBeanInfo implements Clonea
return (Descriptor) nonNullDescriptor(descriptor).clone();
}
+ @Override
public String toString() {
return
getClass().getName() + "[" +
@@ -472,6 +514,7 @@ public class MBeanInfo implements Clonea
* @return true if and only if <code>o</code> is an MBeanInfo that is equal
* to this one according to the rules above.
*/
+ @Override
public boolean equals(Object o) {
if (o == this)
return true;
@@ -491,6 +534,7 @@ public class MBeanInfo implements Clonea
Arrays.equals(p.fastGetNotifications(), fastGetNotifications()));
}
+ @Override
public int hashCode() {
/* Since computing the hashCode is quite expensive, we cache it.
If by some terrible misfortune the computed value is 0, the
@@ -524,8 +568,8 @@ public class MBeanInfo implements Clonea
* a WeakHashMap so that we don't prevent a class from being
* garbage collected just because we know whether it's immutable.
*/
- private static final Map<Class, Boolean> arrayGettersSafeMap =
- new WeakHashMap<Class, Boolean>();
+ private static final Map<Class<?>, Boolean> arrayGettersSafeMap =
+ new WeakHashMap<Class<?>, Boolean>();
/**
* Return true if <code>subclass</code> is known to preserve the
@@ -537,7 +581,7 @@ public class MBeanInfo implements Clonea
* This is obviously not an infallible test for immutability,
* but it works for the public interfaces of the MBean*Info classes.
*/
- static boolean arrayGettersSafe(Class subclass, Class immutableClass) {
+ static boolean arrayGettersSafe(Class<?> subclass, Class<?> immutableClass) {
if (subclass == immutableClass)
return true;
synchronized (arrayGettersSafeMap) {
@@ -714,4 +758,377 @@ public class MBeanInfo implements Clonea
throw new StreamCorruptedException("Got unexpected byte.");
}
}
+
+ /**
+ * <p>Return an {@code MBeanInfo} object that is the same as this one
+ * except that its descriptions are localized in the given locale.
+ * This means the text returned by {@link MBeanInfo#getDescription}
+ * (the description of the MBean itself), and the text returned by the
+ * {@link MBeanFeatureInfo#getDescription getDescription()} method
+ * for every {@linkplain MBeanAttributeInfo attribute}, {@linkplain
+ * MBeanOperationInfo operation}, {@linkplain MBeanConstructorInfo
+ * constructor}, and {@linkplain MBeanNotificationInfo notification}
+ * contained in the {@code MBeanInfo}.</p>
+ *
+ * <p>Here is how the description {@code this.getDescription()} is
+ * localized.</p>
+ *
+ * <p>First, if the {@linkplain #getDescriptor() descriptor}
+ * of this {@code MBeanInfo} contains a field <code><a
+ * href="Descriptor.html#locale">"locale"</a></code>, and the value of
+ * the field is the same as {@code locale.toString()}, then this {@code
+ * MBeanInfo} is returned. Otherwise, localization proceeds as follows,
+ * and the {@code "locale"} field in the returned {@code MBeanInfo} will
+ * be {@code locale.toString()}.
+ *
+ * <p>A <em>{@code className}</em> is determined. If this
+ * {@code MBeanInfo} contains a descriptor with the field
+ * <a href="Descriptor.html#interfaceClassName">{@code
+ * "interfaceClassName"}</a>, then the value of that field is the
+ * {@code className}. Otherwise, it is {@link #getClassName()}.
+ * Everything before the last period (.) in the {@code className} is
+ * the <em>{@code package}</em>, and everything after is the <em>{@code
+ * simpleClassName}</em>. (If there is no period, then the {@code package}
+ * is empty and the {@code simpleClassName} is the same as the {@code
+ * className}.)</p>
+ *
+ * <p>A <em>{@code resourceKey}</em> is determined. If this {@code
+ * MBeanInfo} contains a {@linkplain MBeanInfo#getDescriptor() descriptor}
+ * with a field {@link JMX#DESCRIPTION_RESOURCE_KEY_FIELD
+ * "descriptionResourceKey"}, the value of the field is
+ * the {@code resourceKey}. Otherwise, the {@code resourceKey} is {@code
+ * simpleClassName + ".mbean"}.</p>
+ *
+ * <p>A <em>{@code resourceBundleBaseName}</em> is determined. If
+ * this {@code MBeanInfo} contains a descriptor with a field {@link
+ * JMX#DESCRIPTION_RESOURCE_BUNDLE_BASE_NAME_FIELD
+ * "descriptionResourceBundleBaseName"}, the value of the field
+ * is the {@code resourceBundleBaseName}. Otherwise, the {@code
+ * resourceBundleBaseName} is {@code package + ".MBeanDescriptions"}.
+ *
+ * <p>Then, a {@link java.util.ResourceBundle ResourceBundle} is
+ * determined, using<br> {@link java.util.ResourceBundle#getBundle(String,
+ * Locale, ClassLoader) ResourceBundle.getBundle(resourceBundleBaseName,
+ * locale, loader)}. If this succeeds, and if {@link
+ * java.util.ResourceBundle#getString(String) getString(resourceKey)}
+ * returns a string, then that string is the localized description.
+ * Otherwise, the original description is unchanged.</p>
+ *
+ * <p>A localized description for an {@code MBeanAttributeInfo} is
+ * obtained similarly. The default {@code resourceBundleBaseName}
+ * is the same as above. The default description and the
+ * descriptor fields {@code "descriptionResourceKey"} and {@code
+ * "descriptionResourceBundleBaseName"} come from the {@code
+ * MBeanAttributeInfo} rather than the {@code MBeanInfo}. If the
+ * attribute's {@linkplain MBeanFeatureInfo#getName() name} is {@code
+ * Foo} then its default {@code resourceKey} is {@code simpleClassName +
+ * ".attribute.Foo"}.</p>
+ *
+ * <p>Similar rules apply for operations, constructors, and notifications.
+ * If the name of the operation, constructor, or notification is {@code
+ * Foo} then the default {@code resourceKey} is respectively {@code
+ * simpleClassName + ".operation.Foo"}, {@code simpleClassName +
+ * ".constructor.Foo"}, or {@code simpleClassName + ".notification.Foo"}.
+ * If two operations or constructors have the same name (overloading) then
+ * they have the same default {@code resourceKey}; if different localized
+ * descriptions are needed then a non-default key must be supplied using
+ * {@code "descriptionResourceKey"}.</p>
+ *
+ * <p>Similar rules also apply for descriptions of parameters ({@link
+ * MBeanParameterInfo}). The default {@code resourceKey} for a parameter
+ * whose {@linkplain MBeanFeatureInfo#getName() name} is {@code
+ * Bar} in an operation or constructor called {@code Foo} is {@code
+ * simpleClassName + ".operation.Foo.Bar"} or {@code simpleClassName +
+ * ".constructor.Foo.Bar"} respectively.</p>
+ *
+ * <h4>Example</h4>
+ *
+ * <p>Suppose you have an MBean defined by these two Java source files:</p>
+ *
+ * <pre>
+ * // ConfigurationMBean.java
+ * package com.example;
+ * public interface ConfigurationMBean {
+ * public String getName();
+ * public void save(String fileName);
+ * }
+ *
+ * // Configuration.java
+ * package com.example;
+ * public class Configuration implements ConfigurationMBean {
+ * public Configuration(String defaultName) {
+ * ...
+ * }
+ * ...
+ * }
+ * </pre>
+ *
+ * <p>Then you could define the default descriptions for the MBean, by
+ * including a resource bundle called {@code com/example/MBeanDescriptions}
+ * with the compiled classes. Most often this is done by creating a file
+ * {@code MBeanDescriptions.properties} in the same directory as {@code
+ * ConfigurationMBean.java}. Make sure that this file is copied into the
+ * same place as the compiled classes; in typical build environments that
+ * will be true by default.</p>
+ *
+ * <p>The file {@code com/example/MBeanDescriptions.properties} might
+ * look like this:</p>
+ *
+ * <pre>
+ * # Description of the MBean
+ * ConfigurationMBean.mbean = Configuration manager
+ *
+ * # Description of the Name attribute
+ * ConfigurationMBean.attribute.Name = The name of the configuration
+ *
+ * # Description of the save operation
+ * ConfigurationMBean.operation.save = Save the configuration to a file
+ *
+ * # Description of the parameter to the save operation.
+ * # Parameter names from the original Java source are not available,
+ * # so the default names are p1, p2, etc. If the names were available,
+ * # this would be ConfigurationMBean.operation.save.fileName
+ * ConfigurationMBean.operation.save.p1 = The name of the file
+ *
+ * # Description of the constructor. The default name of a constructor is
+ * # its fully-qualified class name.
+ * ConfigurationMBean.constructor.com.example.Configuration = <!--
+ * -->Constructor with name of default file
+ * # Description of the constructor parameter.
+ * ConfigurationMBean.constructor.com.example.Configuration.p1 = <!--
+ * -->Name of the default file
+ * </pre>
+ *
+ * <p>Starting with this file, you could create descriptions for the French
+ * locale by creating {@code com/example/MBeanDescriptions_fr.properties}.
+ * The keys in this file are the same as before but the text has been
+ * translated:
+ *
+ * <pre>
+ * ConfigurationMBean.mbean = Gestionnaire de configuration
+ *
+ * ConfigurationMBean.attribute.Name = Le nom de la configuration
+ *
+ * ConfigurationMBean.operation.save = Sauvegarder la configuration <!--
+ * -->dans un fichier
+ *
+ * ConfigurationMBean.operation.save.p1 = Le nom du fichier
+ *
+ * ConfigurationMBean.constructor.com.example.Configuration = <!--
+ * -->Constructeur avec nom du fichier par défaut
+ * ConfigurationMBean.constructor.com.example.Configuration.p1 = <!--
+ * -->Nom du fichier par défaut
+ * </pre>
+ *
+ * <p>The descriptions in {@code MBeanDescriptions.properties} and
+ * {@code MBeanDescriptions_fr.properties} will only be consulted if
+ * {@code localizeDescriptions} is called, perhaps because the
+ * MBean Server has been wrapped by {@link
+ * ClientContext#newLocalizeMBeanInfoForwarder} or because the
+ * connector server has been created with the {@link
+ * javax.management.remote.JMXConnectorServer#LOCALIZE_MBEAN_INFO_FORWARDER
+ * LOCALIZE_MBEAN_INFO_FORWARDER} option. If you want descriptions
+ * even when there is no localization step, then you should consider
+ * using {@link Description @Description} annotations. Annotations
+ * provide descriptions by default but are overridden if {@code
+ * localizeDescriptions} is called.</p>
+ *
+ * @param locale the target locale for descriptions. Cannot be null.
+ *
+ * @param loader the {@code ClassLoader} to use for looking up resource
+ * bundles.
+ *
+ * @return an {@code MBeanInfo} with descriptions appropriately localized.
+ *
+ * @throws NullPointerException if {@code locale} is null.
+ */
+ public MBeanInfo localizeDescriptions(Locale locale, ClassLoader loader) {
+ if (locale == null)
+ throw new NullPointerException("locale");
+ Descriptor d = getDescriptor();
+ String mbiLocaleString = (String) d.getFieldValue(JMX.LOCALE_FIELD);
+ if (locale.toString().equals(mbiLocaleString))
+ return this;
+ return new Rewriter(this, locale, loader).getMBeanInfo();
+ }
+
+ private static class Rewriter {
+ private final MBeanInfo mbi;
+ private final ClassLoader loader;
+ private final Locale locale;
+ private final String packageName;
+ private final String simpleClassNamePlusDot;
+ private ResourceBundle defaultBundle;
+ private boolean defaultBundleLoaded;
+
+ // ResourceBundle.getBundle throws NullPointerException
+ // if the loader is null, even though that is perfectly
+ // valid and means the bootstrap loader. So we work
+ // around with a ClassLoader that is equivalent to the
+ // bootstrap loader but is not null.
+ private static final ClassLoader bootstrapLoader =
+ new ClassLoader(null) {};
+
+ Rewriter(MBeanInfo mbi, Locale locale, ClassLoader loader) {
+ this.mbi = mbi;
+ this.locale = locale;
+ if (loader == null)
+ loader = bootstrapLoader;
+ this.loader = loader;
+
+ String intfName = (String)
+ mbi.getDescriptor().getFieldValue("interfaceClassName");
+ if (intfName == null)
+ intfName = mbi.getClassName();
+ int lastDot = intfName.lastIndexOf('.');
+ this.packageName = intfName.substring(0, lastDot + 1);
+ this.simpleClassNamePlusDot = intfName.substring(lastDot + 1) + ".";
+ // Inner classes show up as Outer$Inner so won't match the dot.
+ // When there is no dot, lastDot is -1,
+ // packageName is empty, and simpleClassNamePlusDot is intfName.
+ }
+
+ MBeanInfo getMBeanInfo() {
+ MBeanAttributeInfo[] mbais =
+ rewrite(mbi.getAttributes(), "attribute.");
+ MBeanOperationInfo[] mbois =
+ rewrite(mbi.getOperations(), "operation.");
+ MBeanConstructorInfo[] mbcis =
+ rewrite(mbi.getConstructors(), "constructor.");
+ MBeanNotificationInfo[] mbnis =
+ rewrite(mbi.getNotifications(), "notification.");
+ Descriptor d = mbi.getDescriptor();
+ d = changeLocale(d);
+ String description = getDescription(d, "mbean", "");
+ if (description == null)
+ description = mbi.getDescription();
+ return new MBeanInfo(
+ mbi.getClassName(), description,
+ mbais, mbcis, mbois, mbnis, d);
+ }
+
+ private Descriptor changeLocale(Descriptor d) {
+ if (d.getFieldValue(JMX.LOCALE_FIELD) != null) {
+ Map<String, Object> map = new HashMap<String, Object>();
+ for (String field : d.getFieldNames())
+ map.put(field, d.getFieldValue(field));
+ map.remove(JMX.LOCALE_FIELD);
+ d = new ImmutableDescriptor(map);
+ }
+ return ImmutableDescriptor.union(
+ d, new ImmutableDescriptor(JMX.LOCALE_FIELD + "=" + locale));
+ }
+
+ private String getDescription(
+ Descriptor d, String defaultPrefix, String defaultSuffix) {
+ ResourceBundle bundle = bundleFromDescriptor(d);
+ if (bundle == null)
+ return null;
+ String key =
+ (String) d.getFieldValue(JMX.DESCRIPTION_RESOURCE_KEY_FIELD);
+ if (key == null)
+ key = simpleClassNamePlusDot + defaultPrefix + defaultSuffix;
+ return descriptionFromResource(bundle, key);
+ }
+
+ private <T extends MBeanFeatureInfo> T[] rewrite(
+ T[] features, String resourcePrefix) {
+ for (int i = 0; i < features.length; i++) {
+ T feature = features[i];
+ Descriptor d = feature.getDescriptor();
+ String description =
+ getDescription(d, resourcePrefix, feature.getName());
+ if (description != null &&
+ !description.equals(feature.getDescription())) {
+ features[i] = setDescription(feature, description);
+ }
+ }
+ return features;
+ }
+
+ private <T extends MBeanFeatureInfo> T setDescription(
+ T feature, String description) {
+
+ Object newf;
+ String name = feature.getName();
+ Descriptor d = feature.getDescriptor();
+
+ if (feature instanceof MBeanAttributeInfo) {
+ MBeanAttributeInfo mbai = (MBeanAttributeInfo) feature;
+ newf = new MBeanAttributeInfo(
+ name, mbai.getType(), description,
+ mbai.isReadable(), mbai.isWritable(), mbai.isIs(),
+ d);
+ } else if (feature instanceof MBeanOperationInfo) {
+ MBeanOperationInfo mboi = (MBeanOperationInfo) feature;
+ MBeanParameterInfo[] sig = rewrite(
+ mboi.getSignature(), "operation." + name + ".");
+ newf = new MBeanOperationInfo(
+ name, description, sig,
+ mboi.getReturnType(), mboi.getImpact(), d);
+ } else if (feature instanceof MBeanConstructorInfo) {
+ MBeanConstructorInfo mbci = (MBeanConstructorInfo) feature;
+ MBeanParameterInfo[] sig = rewrite(
+ mbci.getSignature(), "constructor." + name + ".");
+ newf = new MBeanConstructorInfo(
+ name, description, sig, d);
+ } else if (feature instanceof MBeanNotificationInfo) {
+ MBeanNotificationInfo mbni = (MBeanNotificationInfo) feature;
+ newf = new MBeanNotificationInfo(
+ mbni.getNotifTypes(), name, description, d);
+ } else if (feature instanceof MBeanParameterInfo) {
+ MBeanParameterInfo mbpi = (MBeanParameterInfo) feature;
+ newf = new MBeanParameterInfo(
+ name, mbpi.getType(), description, d);
+ } else {
+ logger().log(Level.FINE, "Unknown feature type: " +
+ feature.getClass());
+ newf = feature;
+ }
+
+ return Util.<T>cast(newf);
+ }
+
+ private ResourceBundle bundleFromDescriptor(Descriptor d) {
+ String bundleName = (String) d.getFieldValue(
+ JMX.DESCRIPTION_RESOURCE_BUNDLE_BASE_NAME_FIELD);
+
+ if (bundleName != null)
+ return getBundle(bundleName);
+
+ if (defaultBundleLoaded)
+ return defaultBundle;
+
+ bundleName = packageName + "MBeanDescriptions";
+ defaultBundle = getBundle(bundleName);
+ defaultBundleLoaded = true;
+ return defaultBundle;
+ }
+
+ private String descriptionFromResource(
+ ResourceBundle bundle, String key) {
+ try {
+ return bundle.getString(key);
+ } catch (MissingResourceException e) {
+ logger().log(Level.FINEST, "No resource for " + key, e);
+ } catch (Exception e) {
+ logger().log(Level.FINE, "Bad resource for " + key, e);
+ }
+ return null;
+ }
+
+ private ResourceBundle getBundle(String name) {
+ try {
+ return ResourceBundle.getBundle(name, locale, loader);
+ } catch (Exception e) {
+ logger().log(Level.FINE,
+ "Could not load ResourceBundle " + name, e);
+ return null;
+ }
+ }
+
+ private Logger logger() {
+ return Logger.getLogger("javax.management.locale");
+ }
+ }
}
--- a/src/share/classes/javax/management/MBeanOperationInfo.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/MBeanOperationInfo.java Tue Nov 11 09:07:58 2008 +0000
@@ -308,17 +308,18 @@ public class MBeanOperationInfo extends
wrong should be less than the penalty we would pay if it were
right and we needlessly hashed in the description and the
parameter array. */
+ @Override
public int hashCode() {
return getName().hashCode() ^ getReturnType().hashCode();
}
private static MBeanParameterInfo[] methodSignature(Method method) {
- final Class[] classes = method.getParameterTypes();
+ final Class<?>[] classes = method.getParameterTypes();
final Annotation[][] annots = method.getParameterAnnotations();
return parameters(classes, annots);
}
- static MBeanParameterInfo[] parameters(Class[] classes,
+ static MBeanParameterInfo[] parameters(Class<?>[] classes,
Annotation[][] annots) {
final MBeanParameterInfo[] params =
new MBeanParameterInfo[classes.length];
--- a/src/share/classes/javax/management/MBeanServer.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/MBeanServer.java Tue Nov 11 09:07:58 2008 +0000
@@ -377,19 +377,19 @@ public interface MBeanServer extends MBe
* MBean will not be registered.
* @exception RuntimeMBeanException If the <CODE>postRegister</CODE>
* (<CODE>MBeanRegistration</CODE> interface) method of the MBean throws a
- * <CODE>RuntimeException</CODE>, the <CODE>registerMBean<CODE> method will
+ * <CODE>RuntimeException</CODE>, the <CODE>registerMBean</CODE> method will
* throw a <CODE>RuntimeMBeanException</CODE>, although the MBean
* registration succeeded. In such a case, the MBean will be actually
- * registered even though the <CODE>registerMBean<CODE> method
+ * registered even though the <CODE>registerMBean</CODE> method
* threw an exception. Note that <CODE>RuntimeMBeanException</CODE> can
* also be thrown by <CODE>preRegister</CODE>, in which case the MBean
* will not be registered.
* @exception RuntimeErrorException If the <CODE>postRegister</CODE>
* (<CODE>MBeanRegistration</CODE> interface) method of the MBean throws an
- * <CODE>Error</CODE>, the <CODE>registerMBean<CODE> method will
+ * <CODE>Error</CODE>, the <CODE>registerMBean</CODE> method will
* throw a <CODE>RuntimeErrorException</CODE>, although the MBean
* registration succeeded. In such a case, the MBean will be actually
- * registered even though the <CODE>registerMBean<CODE> method
+ * registered even though the <CODE>registerMBean</CODE> method
* threw an exception. Note that <CODE>RuntimeErrorException</CODE> can
* also be thrown by <CODE>preRegister</CODE>, in which case the MBean
* will not be registered.
@@ -411,6 +411,8 @@ public interface MBeanServer extends MBe
* is sent as described <a href="#notif">above</a>.</p>
*
* @throws RuntimeOperationsException {@inheritDoc}
+ * @throws RuntimeMBeanException {@inheritDoc}
+ * @throws RuntimeErrorException {@inheritDoc}
*/
public void unregisterMBean(ObjectName name)
throws InstanceNotFoundException, MBeanRegistrationException;
--- a/src/share/classes/javax/management/MBeanServerConnection.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/MBeanServerConnection.java Tue Nov 11 09:07:58 2008 +0000
@@ -76,7 +76,9 @@ public interface MBeanServerConnection e
* <CODE>preRegister</CODE> (<CODE>MBeanRegistration</CODE>
* interface) method of the MBean has thrown an exception. The
* MBean will not be registered.
- * @exception RuntimeMBeanException If the <CODE>postRegister</CODE>
+ * @exception RuntimeMBeanException If the MBean's constructor or its
+ * {@code preRegister} or {@code postRegister} method threw
+ * a {@code RuntimeException}. If the <CODE>postRegister</CODE>
* (<CODE>MBeanRegistration</CODE> interface) method of the MBean throws a
* <CODE>RuntimeException</CODE>, the <CODE>createMBean</CODE> method will
* throw a <CODE>RuntimeMBeanException</CODE>, although the MBean creation
@@ -148,7 +150,9 @@ public interface MBeanServerConnection e
* <CODE>preRegister</CODE> (<CODE>MBeanRegistration</CODE>
* interface) method of the MBean has thrown an exception. The
* MBean will not be registered.
- * @exception RuntimeMBeanException If the <CODE>postRegister</CODE>
+ * @exception RuntimeMBeanException If the MBean's constructor or its
+ * {@code preRegister} or {@code postRegister} method threw
+ * a {@code RuntimeException}. If the <CODE>postRegister</CODE>
* (<CODE>MBeanRegistration</CODE> interface) method of the MBean throws a
* <CODE>RuntimeException</CODE>, the <CODE>createMBean</CODE> method will
* throw a <CODE>RuntimeMBeanException</CODE>, although the MBean creation
@@ -223,7 +227,9 @@ public interface MBeanServerConnection e
* <CODE>preRegister</CODE> (<CODE>MBeanRegistration</CODE>
* interface) method of the MBean has thrown an exception. The
* MBean will not be registered.
- * @exception RuntimeMBeanException If the <CODE>postRegister</CODE>
+ * @exception RuntimeMBeanException If the MBean's constructor or its
+ * {@code preRegister} or {@code postRegister} method threw
+ * a {@code RuntimeException}. If the <CODE>postRegister</CODE>
* (<CODE>MBeanRegistration</CODE> interface) method of the MBean throws a
* <CODE>RuntimeException</CODE>, the <CODE>createMBean</CODE> method will
* throw a <CODE>RuntimeMBeanException</CODE>, although the MBean creation
@@ -295,7 +301,9 @@ public interface MBeanServerConnection e
* <CODE>preRegister</CODE> (<CODE>MBeanRegistration</CODE>
* interface) method of the MBean has thrown an exception. The
* MBean will not be registered.
- * @exception RuntimeMBeanException If the <CODE>postRegister</CODE>
+ * @exception RuntimeMBeanException The MBean's constructor or its
+ * {@code preRegister} or {@code postRegister} method threw
+ * a {@code RuntimeException}. If the <CODE>postRegister</CODE>
* (<CODE>MBeanRegistration</CODE> interface) method of the MBean throws a
* <CODE>RuntimeException</CODE>, the <CODE>createMBean</CODE> method will
* throw a <CODE>RuntimeMBeanException</CODE>, although the MBean creation
@@ -524,8 +532,30 @@ public interface MBeanServerConnection e
/**
- * Enables the values of several attributes of a named MBean. The MBean
- * is identified by its object name.
+ * <p>Retrieves the values of several attributes of a named MBean. The MBean
+ * is identified by its object name.</p>
+ *
+ * <p>If one or more attributes cannot be retrieved for some reason, they
+ * will be omitted from the returned {@code AttributeList}. The caller
+ * should check that the list is the same size as the {@code attributes}
+ * array. To discover what problem prevented a given attribute from being
+ * retrieved, call {@link #getAttribute getAttribute} for that attribute.</p>
+ *
+ * <p>Here is an example of calling this method and checking that it
+ * succeeded in retrieving all the requested attributes:</p>
+ *
+ * <pre>
+ * String[] attrNames = ...;
+ * AttributeList list = mbeanServerConnection.getAttributes(objectName, attrNames);
+ * if (list.size() == attrNames.length)
+ * System.out.println("All attributes were retrieved successfully");
+ * else {
+ * {@code List<String>} missing = new {@code ArrayList<String>}(<!--
+ * -->{@link java.util.Arrays#asList Arrays.asList}(attrNames));
+ * missing.removeAll(list.toMap().keySet());
+ * System.out.println("Did not retrieve: " + missing);
+ * }
+ * </pre>
*
* @param name The object name of the MBean from which the
* attributes are retrieved.
@@ -548,6 +578,7 @@ public interface MBeanServerConnection e
public AttributeList getAttributes(ObjectName name, String[] attributes)
throws InstanceNotFoundException, ReflectionException,
IOException;
+
/**
* Sets the value of a specific attribute of a named MBean. The MBean
@@ -584,10 +615,36 @@ public interface MBeanServerConnection e
ReflectionException, IOException;
-
- /**
- * Sets the values of several attributes of a named MBean. The MBean is
- * identified by its object name.
+ /**
+ * <p>Sets the values of several attributes of a named MBean. The MBean is
+ * identified by its object name.</p>
+ *
+ * <p>If one or more attributes cannot be set for some reason, they will be
+ * omitted from the returned {@code AttributeList}. The caller should check
+ * that the input {@code AttributeList} is the same size as the output one.
+ * To discover what problem prevented a given attribute from being retrieved,
+ * it will usually be possible to call {@link #setAttribute setAttribute}
+ * for that attribute, although this is not guaranteed to work. (For
+ * example, the values of two attributes may have been rejected because
+ * they were inconsistent with each other. Setting one of them alone might
+ * be allowed.)<p>
+ *
+ * <p>Here is an example of calling this method and checking that it
+ * succeeded in setting all the requested attributes:</p>
+ *
+ * <pre>
+ * AttributeList inputAttrs = ...;
+ * AttributeList outputAttrs = mbeanServerConnection.setAttributes(<!--
+ * -->objectName, inputAttrs);
+ * if (inputAttrs.size() == outputAttrs.size())
+ * System.out.println("All attributes were set successfully");
+ * else {
+ * {@code List<String>} missing = new {@code ArrayList<String>}(<!--
+ * -->inputAttrs.toMap().keySet());
+ * missing.removeAll(outputAttrs.toMap().keySet());
+ * System.out.println("Did not set: " + missing);
+ * }
+ * </pre>
*
* @param name The object name of the MBean within which the
* attributes are to be set.
@@ -614,7 +671,39 @@ public interface MBeanServerConnection e
throws InstanceNotFoundException, ReflectionException, IOException;
/**
- * Invokes an operation on an MBean.
+ * <p>Invokes an operation on an MBean.</p>
+ *
+ * <p>Because of the need for a {@code signature} to differentiate
+ * possibly-overloaded operations, it is much simpler to invoke operations
+ * through an {@linkplain JMX#newMBeanProxy(MBeanServerConnection, ObjectName,
+ * Class) MBean proxy} where possible. For example, suppose you have a
+ * Standard MBean interface like this:</p>
+ *
+ * <pre>
+ * public interface FooMBean {
+ * public int countMatches(String[] patterns, boolean ignoreCase);
+ * }
+ * </pre>
+ *
+ * <p>The {@code countMatches} operation can be invoked as follows:</p>
+ *
+ * <pre>
+ * String[] myPatterns = ...;
+ * int count = (Integer) mbeanServerConnection.invoke(
+ * objectName,
+ * "countMatches",
+ * new Object[] {myPatterns, true},
+ * new String[] {String[].class.getName(), boolean.class.getName()});
+ * </pre>
+ *
+ * <p>Alternatively, it can be invoked through a proxy as follows:</p>
+ *
+ * <pre>
+ * String[] myPatterns = ...;
+ * FooMBean fooProxy = JMX.newMBeanProxy(
+ * mbeanServerConnection, objectName, FooMBean.class);
+ * int count = fooProxy.countMatches(myPatterns, true);
+ * </pre>
*
* @param name The object name of the MBean on which the method is
* to be invoked.
@@ -622,7 +711,8 @@ public interface MBeanServerConnection e
* @param params An array containing the parameters to be set when
* the operation is invoked
* @param signature An array containing the signature of the
- * operation. The class objects will be loaded using the same
+ * operation, an array of class names in the format returned by
+ * {@link Class#getName()}. The class objects will be loaded using the same
* class loader as the one used for loading the MBean on which the
* operation was invoked.
*
--- a/src/share/classes/javax/management/MBeanServerFactory.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/MBeanServerFactory.java Tue Nov 11 09:07:58 2008 +0000
@@ -747,7 +747,7 @@ public class MBeanServerFactory {
* Load the builder class through the context class loader.
* @param builderClassName The name of the builder class.
**/
- private static Class loadBuilderClass(String builderClassName)
+ private static Class<?> loadBuilderClass(String builderClassName)
throws ClassNotFoundException {
final ClassLoader loader =
Thread.currentThread().getContextClassLoader();
@@ -767,7 +767,7 @@ public class MBeanServerFactory {
* If any checked exception needs to be thrown, it is embedded in
* a JMRuntimeException.
**/
- private static MBeanServerBuilder newBuilder(Class builderClass) {
+ private static MBeanServerBuilder newBuilder(Class<?> builderClass) {
try {
final Object abuilder = builderClass.newInstance();
return (MBeanServerBuilder)abuilder;
@@ -792,7 +792,7 @@ public class MBeanServerFactory {
String builderClassName = AccessController.doPrivileged(act);
try {
- final Class newBuilderClass;
+ final Class<?> newBuilderClass;
if (builderClassName == null || builderClassName.length() == 0)
newBuilderClass = MBeanServerBuilder.class;
else
@@ -800,7 +800,7 @@ public class MBeanServerFactory {
// Check whether a new builder needs to be created
if (builder != null) {
- final Class builderClass = builder.getClass();
+ final Class<?> builderClass = builder.getClass();
if (newBuilderClass == builderClass)
return; // no need to create a new builder...
}
--- a/src/share/classes/javax/management/MBeanServerInvocationHandler.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/MBeanServerInvocationHandler.java Tue Nov 11 09:07:58 2008 +0000
@@ -253,12 +253,12 @@ public class MBeanServerInvocationHandle
boolean notificationBroadcaster) {
final InvocationHandler handler =
new MBeanServerInvocationHandler(connection, objectName);
- final Class[] interfaces;
+ final Class<?>[] interfaces;
if (notificationBroadcaster) {
interfaces =
- new Class[] {interfaceClass, NotificationEmitter.class};
+ new Class<?>[] {interfaceClass, NotificationEmitter.class};
} else
- interfaces = new Class[] {interfaceClass};
+ interfaces = new Class<?>[] {interfaceClass};
Object proxy =
Proxy.newProxyInstance(interfaceClass.getClassLoader(),
@@ -269,7 +269,7 @@ public class MBeanServerInvocationHandle
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
- final Class methodClass = method.getDeclaringClass();
+ final Class<?> methodClass = method.getDeclaringClass();
if (methodClass.equals(NotificationBroadcaster.class)
|| methodClass.equals(NotificationEmitter.class))
@@ -285,8 +285,8 @@ public class MBeanServerInvocationHandle
return p.invoke(connection, objectName, method, args);
} else {
final String methodName = method.getName();
- final Class[] paramTypes = method.getParameterTypes();
- final Class returnType = method.getReturnType();
+ final Class<?>[] paramTypes = method.getParameterTypes();
+ final Class<?> returnType = method.getReturnType();
/* Inexplicably, InvocationHandler specifies that args is null
when the method takes no arguments rather than a
@@ -361,7 +361,13 @@ public class MBeanServerInvocationHandle
if (p != null)
return p;
}
- p = new MXBeanProxy(mxbeanInterface, mappingFactory);
+ try {
+ p = new MXBeanProxy(mxbeanInterface, mappingFactory);
+ } catch (IllegalArgumentException e) {
+ String msg = "Cannot make MXBean proxy for " +
+ mxbeanInterface.getName() + ": " + e.getMessage();
+ throw new IllegalArgumentException(msg, e.getCause());
+ }
classToProxy.put(mxbeanInterface, new WeakReference<MXBeanProxy>(p));
return p;
}
@@ -452,7 +458,7 @@ public class MBeanServerInvocationHandle
return true;
if (methodName.equals("equals")
&& Arrays.equals(method.getParameterTypes(),
- new Class[] {Object.class})
+ new Class<?>[] {Object.class})
&& isLocal(proxy, method))
return true;
return false;
--- a/src/share/classes/javax/management/MBeanServerNotification.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/MBeanServerNotification.java Tue Nov 11 09:07:58 2008 +0000
@@ -27,14 +27,69 @@ package javax.management;
/**
- * Represents a notification emitted by the MBean server through the MBeanServerDelegate MBean.
+ * Represents a notification emitted by the MBean Server through the MBeanServerDelegate MBean.
* The MBean Server emits the following types of notifications: MBean registration, MBean
- * de-registration.
+ * unregistration.
* <P>
- * To receive to MBeanServerNotifications, you need to be declared as listener to
- * the {@link javax.management.MBeanServerDelegate javax.management.MBeanServerDelegate} MBean
- * that represents the MBeanServer. The ObjectName of the MBeanServerDelegate is:
+ * To receive MBeanServerNotifications, you need to register a listener with
+ * the {@link MBeanServerDelegate MBeanServerDelegate} MBean
+ * that represents the MBeanServer. The ObjectName of the MBeanServerDelegate is
+ * {@link MBeanServerDelegate#DELEGATE_NAME}, which is
* <CODE>JMImplementation:type=MBeanServerDelegate</CODE>.
+ *
+ * <p>The following code prints a message every time an MBean is registered
+ * or unregistered in the MBean Server {@code mbeanServer}:</p>
+ *
+ * <pre>
+ * private static final NotificationListener printListener = new NotificationListener() {
+ * public void handleNotification(Notification n, Object handback) {
+ * if (!(n instanceof MBeanServerNotification)) {
+ * System.out.println("Ignored notification of class " + n.getClass().getName());
+ * return;
+ * }
+ * MBeanServerNotification mbsn = (MBeanServerNotification) n;
+ * String what;
+ * if (n.getType().equals(MBeanServerNotification.REGISTRATION_NOTIFICATION))
+ * what = "MBean registered";
+ * else if (n.getType().equals(MBeanServerNotification.UNREGISTRATION_NOTIFICATION))
+ * what = "MBean unregistered";
+ * else
+ * what = "Unknown type " + n.getType();
+ * System.out.println("Received MBean Server notification: " + what + ": " +
+ * mbsn.getMBeanName());
+ * };
+ *
+ * ...
+ * mbeanServer.addNotificationListener(
+ * MBeanServerDelegate.DELEGATE_NAME, printListener, null, null);
+ * </pre>
+ *
+ * <p>The following code prints a message every time an MBean is registered
+ * or unregistered in the MBean Server {@code mbeanServer}:</p>
+ *
+ * <pre>
+ * private static final NotificationListener printListener = new NotificationListener() {
+ * public void handleNotification(Notification n, Object handback) {
+ * if (!(n instanceof MBeanServerNotification)) {
+ * System.out.println("Ignored notification of class " + n.getClass().getName());
+ * return;
+ * }
+ * MBeanServerNotification mbsn = (MBeanServerNotification) n;
+ * String what;
+ * if (n.getType().equals(MBeanServerNotification.REGISTRATION_NOTIFICATION))
+ * what = "MBean registered";
+ * else if (n.getType().equals(MBeanServerNotification.UNREGISTRATION_NOTIFICATION))
+ * what = "MBean unregistered";
+ * else
+ * what = "Unknown type " + n.getType();
+ * System.out.println("Received MBean Server notification: " + what + ": " +
+ * mbsn.getMBeanName());
+ * };
+ *
+ * ...
+ * mbeanServer.addNotificationListener(
+ * MBeanServerDelegate.DELEGATE_NAME, printListener, null, null);
+ * </pre>
*
* @since 1.5
*/
--- a/src/share/classes/javax/management/Notification.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/Notification.java Tue Nov 11 09:07:58 2008 +0000
@@ -54,7 +54,7 @@ import com.sun.jmx.mbeanserver.GetProper
* @since 1.5
*/
@SuppressWarnings("serial") // serialVersionUID is not constant
-public class Notification extends EventObject {
+public class Notification extends EventObject implements Cloneable {
// Serialization compatibility stuff:
// Two serial forms are supported in this class. The selected form depends
@@ -244,6 +244,26 @@ public class Notification extends EventO
}
/**
+ * <p>Creates and returns a copy of this object. The copy is created as
+ * described for {@link Object#clone()}. This means, first, that the
+ * class of the object will be the same as the class of this object, and,
+ * second, that the copy is a "shallow copy". Fields of this notification
+ * are not themselves copied. In particular, the {@linkplain
+ * #getUserData user data} of the copy is the same object as the
+ * original.</p>
+ *
+ * @return a copy of this object.
+ */
+ @Override
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ /**
* Sets the source.
*
* @param source the new source for this object.
@@ -285,8 +305,10 @@ public class Notification extends EventO
/**
* Get the notification type.
*
- * @return The notification type. It's a string expressed in a dot notation similar
- * to Java properties. An example of a notification type is network.alarm.router .
+ * @return The notification type. It's a string expressed in a dot notation
+ * similar to Java properties. It is recommended that the notification type
+ * should follow the reverse-domain-name convention used by Java package
+ * names. An example of a notification type is com.example.alarm.router.
*/
public String getType() {
return type ;
@@ -317,15 +339,26 @@ public class Notification extends EventO
/**
* Get the notification message.
*
- * @return The message string of this notification object. It contains in a string,
- * which could be the explanation of the notification for displaying to a user
- *
+ * @return The message string of this notification object.
+ *
+ * @see #setMessage
*/
public String getMessage() {
return message ;
}
/**
+ * Set the notification message.
+ *
+ * @param message the new notification message.
+ *
+ * @see #getMessage
+ */
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ /**
* Get the user data.
*
* @return The user data object. It is used for whatever data
@@ -355,6 +388,7 @@ public class Notification extends EventO
*
* @return A String representation of this notification.
*/
+ @Override
public String toString() {
return super.toString()+"[type="+type+"][message="+message+"]";
}
--- a/src/share/classes/javax/management/NotificationListener.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/NotificationListener.java Tue Nov 11 09:07:58 2008 +0000
@@ -39,11 +39,10 @@ public interface NotificationListener ex
* blocking its notification broadcaster.
*
* @param notification The notification.
- * @param handback An opaque object which helps the listener to associate information
- * regarding the MBean emitter. This object is passed to the MBean during the
- * addListener call and resent, without modification, to the listener. The MBean object
- * should not use or modify the object.
- *
+ * @param handback An opaque object which helps the listener to associate
+ * information regarding the MBean emitter. This object is passed to the
+ * addNotificationListener call and resent, without modification, to the
+ * listener.
*/
- public void handleNotification(Notification notification, Object handback) ;
+ public void handleNotification(Notification notification, Object handback);
}
--- a/src/share/classes/javax/management/QueryNotificationFilter.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/QueryNotificationFilter.java Tue Nov 11 09:07:58 2008 +0000
@@ -26,7 +26,6 @@ package javax.management;
package javax.management;
import com.sun.jmx.mbeanserver.NotificationMBeanSupport;
-import com.sun.jmx.mbeanserver.Util;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -42,6 +41,11 @@ import java.util.Set;
* class. Writing a custom implementation requires you to deploy it
* on both the client and the server in the remote case, so using this class
* instead is recommended where possible.</p>
+ *
+ * <p>Because this class was introduced in version 2.0 of the JMX API,
+ * it may not be present on a remote JMX agent that is running an earlier
+ * version. The method {@link JMX#getSpecificationVersion
+ * JMX.getSpecificationVersion} can be used to determine the remote version.</p>
*
* <p>This class uses the {@linkplain Query Query API} to specify the
* filtering logic. For example, to select only notifications where the
--- a/src/share/classes/javax/management/StandardMBean.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/StandardMBean.java Tue Nov 11 09:07:58 2008 +0000
@@ -689,7 +689,7 @@ public class StandardMBean implements Dy
getImplementationClass().getName());
}
- MBeanSupport msupport = mbean;
+ MBeanSupport<?> msupport = mbean;
final MBeanInfo bi = msupport.getMBeanInfo();
final Object impl = msupport.getWrappedObject();
@@ -1391,8 +1391,8 @@ public class StandardMBean implements Dy
* garbage collected just because we know whether its MBeanInfo
* is immutable.
*/
- private static final Map<Class, Boolean> mbeanInfoSafeMap =
- new WeakHashMap<Class, Boolean>();
+ private static final Map<Class<?>, Boolean> mbeanInfoSafeMap =
+ new WeakHashMap<Class<?>, Boolean>();
/**
* Return true if {@code subclass} is known to preserve the immutability
@@ -1438,9 +1438,9 @@ public class StandardMBean implements Dy
private static class MBeanInfoSafeAction
implements PrivilegedAction<Boolean> {
- private final Class subclass;
-
- MBeanInfoSafeAction(Class subclass) {
+ private final Class<?> subclass;
+
+ MBeanInfoSafeAction(Class<?> subclass) {
this.subclass = subclass;
}
@@ -1454,13 +1454,13 @@ public class StandardMBean implements Dy
// Check for "MBeanInfo getCachedMBeanInfo()" method.
//
if (overrides(subclass, StandardMBean.class,
- "getCachedMBeanInfo", (Class[]) null))
+ "getCachedMBeanInfo", (Class<?>[]) null))
return false;
// Check for "MBeanInfo getMBeanInfo()" method.
//
if (overrides(subclass, StandardMBean.class,
- "getMBeanInfo", (Class[]) null))
+ "getMBeanInfo", (Class<?>[]) null))
return false;
// Check for "MBeanNotificationInfo[] getNotificationInfo()"
@@ -1473,7 +1473,7 @@ public class StandardMBean implements Dy
//
if (StandardEmitterMBean.class.isAssignableFrom(subclass))
if (overrides(subclass, StandardEmitterMBean.class,
- "getNotificationInfo", (Class[]) null))
+ "getNotificationInfo", (Class<?>[]) null))
return false;
return true;
}
--- a/src/share/classes/javax/management/event/EventClient.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/event/EventClient.java Tue Nov 11 09:07:58 2008 +0000
@@ -29,7 +29,6 @@ import com.sun.jmx.event.LeaseRenewer;
import com.sun.jmx.event.LeaseRenewer;
import com.sun.jmx.event.ReceiverBuffer;
import com.sun.jmx.event.RepeatedSingletonJob;
-import com.sun.jmx.namespace.JMXNamespaceUtils;
import com.sun.jmx.mbeanserver.PerThreadGroupPool;
import com.sun.jmx.remote.util.ClassLogger;
@@ -58,7 +57,6 @@ import javax.management.NotificationFilt
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectName;
-import javax.management.remote.JMXConnector;
import javax.management.remote.NotificationResult;
import javax.management.remote.TargetedNotification;
@@ -117,23 +115,24 @@ public class EventClient implements Even
public static final String NONFATAL = "jmx.event.service.nonfatal";
/**
- * <p>A notification string type used by an {@code EventClient} object to
- * inform a listener added by {@code #addEventClientListener} that it
- * has detected that notifications have been lost. The {@link
- * Notification#getUserData() userData} of the notification is a Long which
- * is an upper bound on the number of lost notifications that have just
- * been detected.</p>
+ * <p>A notification string type used by an {@code EventClient} object
+ * to inform a listener added by {@link #addEventClientListener
+ * addEventClientListener} that it has detected that notifications have
+ * been lost. The {@link Notification#getUserData() userData} of the
+ * notification is a Long which is an upper bound on the number of lost
+ * notifications that have just been detected.</p>
*
* @see #addEventClientListener
*/
public static final String NOTIFS_LOST = "jmx.event.service.notifs.lost";
/**
- * The default lease time, {@value}, in milliseconds.
+ * The default lease time that EventClient instances will request, in
+ * milliseconds. This value is {@value}.
*
* @see EventClientDelegateMBean#lease
*/
- public static final long DEFAULT_LEASE_TIMEOUT = 300000;
+ public static final long DEFAULT_REQUESTED_LEASE_TIME = 300000;
/**
* <p>Constructs a default {@code EventClient} object.</p>
@@ -173,7 +172,7 @@ public class EventClient implements Even
*/
public EventClient(EventClientDelegateMBean delegate)
throws IOException {
- this(delegate, null, null, null, DEFAULT_LEASE_TIMEOUT);
+ this(delegate, null, null, null, DEFAULT_REQUESTED_LEASE_TIME);
}
/**
@@ -196,7 +195,7 @@ public class EventClient implements Even
* If {@code null}, a default scheduler will be used.
* @param requestedLeaseTime The lease time used to keep this client alive
* in the {@link EventClientDelegateMBean}. A value of zero is equivalent
- * to the {@linkplain #DEFAULT_LEASE_TIMEOUT default value}.
+ * to the {@linkplain #DEFAULT_REQUESTED_LEASE_TIME default value}.
*
* @throws IllegalArgumentException If {@code delegate} is null.
* @throws IOException If an I/O error occurs when communicating with the
@@ -213,7 +212,7 @@ public class EventClient implements Even
}
if (requestedLeaseTime == 0)
- requestedLeaseTime = DEFAULT_LEASE_TIMEOUT;
+ requestedLeaseTime = DEFAULT_REQUESTED_LEASE_TIME;
else if (requestedLeaseTime < 0) {
throw new IllegalArgumentException(
"Negative lease time: " + requestedLeaseTime);
@@ -269,7 +268,13 @@ public class EventClient implements Even
new ScheduledThreadPoolExecutor(20, daemonThreadFactory);
executor.setKeepAliveTime(1, TimeUnit.SECONDS);
executor.allowCoreThreadTimeOut(true);
- executor.setRemoveOnCancelPolicy(true);
+ if (setRemoveOnCancelPolicy != null) {
+ try {
+ setRemoveOnCancelPolicy.invoke(executor, true);
+ } catch (Exception e) {
+ logger.trace("setRemoveOnCancelPolicy", e);
+ }
+ }
// By default, a ScheduledThreadPoolExecutor will keep jobs
// in its queue even after they have been cancelled. They
// will only be removed when their scheduled time arrives.
@@ -277,12 +282,25 @@ public class EventClient implements Even
// this EventClient, this can lead to a moderately large number
// of objects remaining referenced until the renewal time
// arrives. Hence the above call, which removes the job from
- // the queue as soon as it is cancelled.
+ // the queue as soon as it is cancelled. Since the call is
+ // new with JDK 7, we invoke it via reflection to make it
+ // easier to use this code on JDK 6.
return executor;
}
};
return leaseRenewerThreadPool.getThreadPoolExecutor(create);
-
+ }
+
+ private static final Method setRemoveOnCancelPolicy;
+ static {
+ Method m;
+ try {
+ m = ScheduledThreadPoolExecutor.class.getMethod(
+ "setRemoveOnCancelPolicy", boolean.class);
+ } catch (Exception e) {
+ m = null;
+ }
+ setRemoveOnCancelPolicy = m;
}
/**
@@ -577,8 +595,13 @@ public class EventClient implements Even
}
/**
- * Returns the set of listeners that have been added through
- * this {@code EventClient} and not subsequently removed.
+ * <p>Returns the collection of listeners that have been added through
+ * this {@code EventClient} and not subsequently removed. The returned
+ * collection contains one entry for every listener added with
+ * {@link #addNotificationListener addNotificationListener} or
+ * {@link #subscribe subscribe} and not subsequently removed with
+ * {@link #removeNotificationListener removeNotificationListener} or
+ * {@link #unsubscribe unsubscribe}, respectively.</p>
*
* @return A collection of listener information. Empty if there are no
* current listeners or if this {@code EventClient} has been {@linkplain
@@ -927,8 +950,10 @@ public class EventClient implements Even
private final static MBeanNotificationInfo[] myInfo =
new MBeanNotificationInfo[] {
new MBeanNotificationInfo(
- new String[] {FAILED, NOTIFS_LOST},
- Notification.class.getName(), "")};
+ new String[] {FAILED, NONFATAL, NOTIFS_LOST},
+ Notification.class.getName(),
+ "Notifications that can be sent to a listener added with " +
+ "EventClient.addEventClientListener")};
private final NotificationBroadcasterSupport broadcaster =
new NotificationBroadcasterSupport();
@@ -1035,7 +1060,7 @@ public class EventClient implements Even
final public EventClient call() throws Exception {
EventClientDelegateMBean ecd = EventClientDelegate.getProxy(conn);
return new EventClient(ecd, eventRelay, null, null,
- DEFAULT_LEASE_TIMEOUT);
+ DEFAULT_REQUESTED_LEASE_TIME);
}
};
@@ -1073,24 +1098,6 @@ public class EventClient implements Even
return clientId;
}
- /**
- * Returns a JMX Connector that will use an {@link EventClient}
- * to subscribe for notifications. If the server doesn't have
- * an {@link EventClientDelegateMBean}, then the connector will
- * use the legacy notification mechanism instead.
- *
- * @param wrapped The underlying JMX Connector wrapped by the returned
- * connector.
- *
- * @return A JMX Connector that will uses an {@link EventClient}, if
- * available.
- *
- * @see EventClient#getEventClientConnection(MBeanServerConnection)
- */
- public static JMXConnector withEventClient(final JMXConnector wrapped) {
- return JMXNamespaceUtils.withEventClient(wrapped);
- }
-
private static final PerThreadGroupPool<ScheduledThreadPoolExecutor>
leaseRenewerThreadPool = PerThreadGroupPool.make();
}
--- a/src/share/classes/javax/management/event/EventClientDelegate.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/event/EventClientDelegate.java Tue Nov 11 09:07:58 2008 +0000
@@ -104,8 +104,8 @@ public class EventClientDelegate impleme
public static EventClientDelegate getEventClientDelegate(MBeanServer server) {
EventClientDelegate delegate = null;
synchronized(delegateMap) {
- final WeakReference wrf = delegateMap.get(server);
- delegate = (wrf == null) ? null : (EventClientDelegate)wrf.get();
+ final WeakReference<EventClientDelegate> wrf = delegateMap.get(server);
+ delegate = (wrf == null) ? null : wrf.get();
if (delegate == null) {
delegate = new EventClientDelegate(server);
@@ -149,6 +149,7 @@ public class EventClientDelegate impleme
// of a setMBeanServer on some other forwarder later in the chain.
private static class Forwarder extends SingleMBeanForwarder {
+ private MBeanServer loopMBS;
private static class UnsupportedInvocationHandler
implements InvocationHandler {
@@ -173,7 +174,11 @@ public class EventClientDelegate impleme
private volatile boolean madeECD;
Forwarder() {
- super(OBJECT_NAME, makeUnsupportedECD());
+ super(OBJECT_NAME, makeUnsupportedECD(), true);
+ }
+
+ synchronized void setLoopMBS(MBeanServer loopMBS) {
+ this.loopMBS = loopMBS;
}
@Override
@@ -186,7 +191,7 @@ public class EventClientDelegate impleme
AccessController.doPrivileged(
new PrivilegedAction<EventClientDelegate>() {
public EventClientDelegate run() {
- return getEventClientDelegate(Forwarder.this);
+ return getEventClientDelegate(loopMBS);
}
});
DynamicMBean mbean = new StandardMBean(
@@ -208,11 +213,46 @@ public class EventClientDelegate impleme
* that are targeted for that MBean and handles them itself. All other
* requests are forwarded to the next element in the forwarder chain.</p>
*
+ * @param nextMBS the next {@code MBeanServer} in the chain of forwarders,
+ * which might be another {@code MBeanServerForwarder} or a plain {@code
+ * MBeanServer}. This is the object to which {@code MBeanServer} requests
+ * that do not concern the {@code EventClientDelegateMBean} are sent.
+ * It will be the value of {@link MBeanServerForwarder#getMBeanServer()
+ * getMBeanServer()} on the returned object, and can be changed with {@link
+ * MBeanServerForwarder#setMBeanServer setMBeanServer}. It can be null but
+ * must be set to a non-null value before any {@code MBeanServer} requests
+ * arrive.
+ *
+ * @param loopMBS the {@code MBeanServer} to which requests from the
+ * {@code EventClientDelegateMBean} should be sent. For example,
+ * when you invoke the {@link EventClientDelegateMBean#addListener
+ * addListener} operation on the {@code EventClientDelegateMBean}, it will
+ * result in a call to {@link
+ * MBeanServer#addNotificationListener(ObjectName, NotificationListener,
+ * NotificationFilter, Object) addNotificationListener} on this object.
+ * If this parameter is null, then these requests will be sent to the
+ * newly-created {@code MBeanServerForwarder}. Usually the parameter will
+ * either be null or will be the result of {@link
+ * javax.management.remote.JMXConnectorServer#getSystemMBeanServerForwarder()
+ * getSystemMBeanServerForwarder()} for the connector server in which
+ * this forwarder will be installed.
+ *
* @return a new {@code MBeanServerForwarder} that simulates the existence
* of an {@code EventClientDelegateMBean}.
+ *
+ * @see javax.management.remote.JMXConnectorServer#installStandardForwarders
*/
- public static MBeanServerForwarder newForwarder() {
- return new Forwarder();
+ public static MBeanServerForwarder newForwarder(
+ MBeanServer nextMBS, MBeanServer loopMBS) {
+ Forwarder mbsf = new Forwarder();
+ // We must setLoopMBS before setMBeanServer, because when we
+ // setMBeanServer that will call getEventClientDelegate(loopMBS).
+ if (loopMBS == null)
+ loopMBS = mbsf;
+ mbsf.setLoopMBS(loopMBS);
+ if (nextMBS != null)
+ mbsf.setMBeanServer(nextMBS);
+ return mbsf;
}
/**
@@ -282,7 +322,7 @@ public class EventClientDelegate impleme
Constructor<?> foundCons = null;
if (sig == null)
sig = new String[0];
- for (Constructor cons : c.getConstructors()) {
+ for (Constructor<?> cons : c.getConstructors()) {
Class<?>[] types = cons.getParameterTypes();
String[] consSig = new String[types.length];
for (int i = 0; i < types.length; i++)
@@ -437,10 +477,9 @@ public class EventClientDelegate impleme
// private classes
// ------------------------------------
private class ClientInfo {
- String clientId;
- EventBuffer buffer;
- NotificationListener clientListener;
- Map<Integer, AddedListener> listenerInfoMap =
+ final String clientId;
+ final NotificationListener clientListener;
+ final Map<Integer, AddedListener> listenerInfoMap =
new HashMap<Integer, AddedListener>();
ClientInfo(String clientId, EventForwarder forwarder) {
@@ -703,7 +742,8 @@ public class EventClientDelegate impleme
clientInfo = clientInfoMap.get(clientId);
if (clientInfo == null) {
- throw new EventClientNotFoundException("The client is not found.");
+ throw new EventClientNotFoundException(
+ "Client not found (id " + clientId + ")");
}
return clientInfo;
--- a/src/share/classes/javax/management/event/EventClientDelegateMBean.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/event/EventClientDelegateMBean.java Tue Nov 11 09:07:58 2008 +0000
@@ -51,7 +51,8 @@ import javax.management.remote.Notificat
* and the MBean Server, that will intercept accesses to the Event Client
* Delegate MBean and treat them as the real MBean would. This forwarder is
* inserted by default with the standard RMI Connector Server, and can also
- * be created explicitly using {@link EventClientDelegate#newForwarder()}.
+ * be created explicitly using {@link EventClientDelegate#newForwarder
+ * EventClientDelegate.newForwarder}.
*
* <li><p>A variant on the above is to replace the MBean Server that is
* used locally with a forwarder as described above. Since
@@ -61,9 +62,7 @@ import javax.management.remote.Notificat
*
* <pre>
* MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); // or whatever
- * MBeanServerForwarder mbsf = EventClientDelegate.newForwarder();
- * mbsf.setMBeanServer(mbs);
- * mbs = mbsf;
+ * mbs = EventClientDelegate.newForwarder(mbs, null);
* // now use mbs just as you did before, but it will have an EventClientDelegate
* </pre>
*
--- a/src/share/classes/javax/management/event/EventRelay.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/event/EventRelay.java Tue Nov 11 09:07:58 2008 +0000
@@ -27,7 +27,6 @@ package javax.management.event;
import java.io.IOException;
import java.util.concurrent.Executors; // for javadoc
-import java.util.concurrent.ScheduledFuture;
/**
* This interface is used to specify a way to receive
--- a/src/share/classes/javax/management/event/EventSubscriber.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/event/EventSubscriber.java Tue Nov 11 09:07:58 2008 +0000
@@ -350,8 +350,7 @@ public class EventSubscriber implements
static {
QueryExp broadcasterExp;
try {
- final Method m = Query.class.getMethod("isInstanceOf",
- new Class[] {String.class});
+ final Method m = Query.class.getMethod("isInstanceOf", String.class);
broadcasterExp = (QueryExp)m.invoke(Query.class,
new Object[] {NotificationBroadcaster.class.getName()});
} catch (Exception e) {
--- a/src/share/classes/javax/management/event/package-info.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/event/package-info.java Tue Nov 11 09:07:58 2008 +0000
@@ -83,8 +83,8 @@
* javax.management.event.EventClientDelegateMBean EventClientDelegateMBean}
* must be registered in the MBean Server, or the connector server must
* be configured to simulate the existence of this MBean, for example
- * using {@link javax.management.event.EventClientDelegate#newForwarder()
- * EventClientDelegate.newForwarder()}. The standard RMI connector is so
+ * using {@link javax.management.event.EventClientDelegate#newForwarder
+ * EventClientDelegate.newForwarder}. The standard RMI connector is so
* configured by default. The {@code EventClientDelegateMBean} documentation
* has further details.</p>
*
--- a/src/share/classes/javax/management/loading/DefaultLoaderRepository.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/loading/DefaultLoaderRepository.java Tue Nov 11 09:07:58 2008 +0000
@@ -69,7 +69,7 @@ public class DefaultLoaderRepository {
* @exception ClassNotFoundException The specified class could not be
* found.
*/
- public static Class loadClass(String className)
+ public static Class<?> loadClass(String className)
throws ClassNotFoundException {
MBEANSERVER_LOGGER.logp(Level.FINEST,
DefaultLoaderRepository.class.getName(),
@@ -93,7 +93,7 @@ public class DefaultLoaderRepository {
* @exception ClassNotFoundException The specified class could not be
* found.
*/
- public static Class loadClassWithout(ClassLoader loader,
+ public static Class<?> loadClassWithout(ClassLoader loader,
String className)
throws ClassNotFoundException {
MBEANSERVER_LOGGER.logp(Level.FINEST,
@@ -102,12 +102,11 @@ public class DefaultLoaderRepository {
return load(loader, className);
}
- private static Class load(ClassLoader without, String className)
+ private static Class<?> load(ClassLoader without, String className)
throws ClassNotFoundException {
- final List mbsList = MBeanServerFactory.findMBeanServer(null);
+ final List<MBeanServer> mbsList = MBeanServerFactory.findMBeanServer(null);
- for (Iterator it = mbsList.iterator(); it.hasNext(); ) {
- MBeanServer mbs = (MBeanServer) it.next();
+ for (MBeanServer mbs : mbsList) {
ClassLoaderRepository clr = mbs.getClassLoaderRepository();
try {
return clr.loadClassWithout(without, className);
--- a/src/share/classes/javax/management/loading/MLet.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/loading/MLet.java Tue Nov 11 09:07:58 2008 +0000
@@ -1291,7 +1291,7 @@ public class MLet extends java.net.URLCl
if (c != null) {
try {
Constructor<?> cons =
- c.getConstructor(new Class[] {String.class});
+ c.getConstructor(String.class);
Object[] oo = new Object[1];
oo[0]=param;
return(cons.newInstance(oo));
--- a/src/share/classes/javax/management/loading/MLetObjectInputStream.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/loading/MLetObjectInputStream.java Tue Nov 11 09:07:58 2008 +0000
@@ -55,30 +55,30 @@ class MLetObjectInputStream extends Obje
this.loader = loader;
}
- private Class primitiveType(char c) {
+ private Class<?> primitiveType(char c) {
switch(c) {
- case 66: /* 'B' */
+ case 'B':
return Byte.TYPE;
- case 67: /* 'C' */
+ case 'C':
return Character.TYPE;
- case 68: /* 'D' */
+ case 'D':
return Double.TYPE;
- case 70: /* 'F' */
+ case 'F':
return Float.TYPE;
- case 73: /* 'I' */
+ case 'I':
return Integer.TYPE;
- case 74: /* 'J' */
+ case 'J':
return Long.TYPE;
- case 83: /* 'S' */
+ case 'S':
return Short.TYPE;
- case 90: /* 'Z' */
+ case 'Z':
return Boolean.TYPE;
}
return null;
@@ -87,14 +87,15 @@ class MLetObjectInputStream extends Obje
/**
* Use the given ClassLoader rather than using the system class
*/
- protected Class resolveClass(ObjectStreamClass objectstreamclass)
+ @Override
+ protected Class<?> resolveClass(ObjectStreamClass objectstreamclass)
throws IOException, ClassNotFoundException {
String s = objectstreamclass.getName();
if (s.startsWith("[")) {
int i;
for (i = 1; s.charAt(i) == '['; i++);
- Class class1;
+ Class<?> class1;
if (s.charAt(i) == 'L') {
class1 = loader.loadClass(s.substring(i + 1, s.length() - 1));
} else {
--- a/src/share/classes/javax/management/modelmbean/DescriptorSupport.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/modelmbean/DescriptorSupport.java Tue Nov 11 09:07:58 2008 +0000
@@ -589,7 +589,7 @@ public class DescriptorSupport
int numberOfEntries = descriptorMap.size();
String[] responseFields = new String[numberOfEntries];
- Set returnedSet = descriptorMap.entrySet();
+ Set<Map.Entry<String, Object>> returnedSet = descriptorMap.entrySet();
int i = 0;
@@ -598,8 +598,9 @@ public class DescriptorSupport
DescriptorSupport.class.getName(),
"getFields()", "Returning " + numberOfEntries + " fields");
}
- for (Iterator iter = returnedSet.iterator(); iter.hasNext(); i++) {
- Map.Entry currElement = (Map.Entry) iter.next();
+ for (Iterator<Map.Entry<String, Object>> iter = returnedSet.iterator();
+ iter.hasNext(); i++) {
+ Map.Entry<String, Object> currElement = iter.next();
if (currElement == null) {
if (MODELMBEAN_LOGGER.isLoggable(Level.FINEST)) {
@@ -642,7 +643,7 @@ public class DescriptorSupport
int numberOfEntries = descriptorMap.size();
String[] responseFields = new String[numberOfEntries];
- Set returnedSet = descriptorMap.entrySet();
+ Set<Map.Entry<String, Object>> returnedSet = descriptorMap.entrySet();
int i = 0;
@@ -653,8 +654,9 @@ public class DescriptorSupport
"Returning " + numberOfEntries + " fields");
}
- for (Iterator iter = returnedSet.iterator(); iter.hasNext(); i++) {
- Map.Entry currElement = (Map.Entry) iter.next();
+ for (Iterator<Map.Entry<String, Object>> iter = returnedSet.iterator();
+ iter.hasNext(); i++) {
+ Map.Entry<String, Object> currElement = iter.next();
if (( currElement == null ) || (currElement.getKey() == null)) {
if (MODELMBEAN_LOGGER.isLoggable(Level.FINEST)) {
@@ -700,9 +702,8 @@ public class DescriptorSupport
}
if (fieldNames == null) {
- for (Iterator iter = descriptorMap.values().iterator();
- iter.hasNext(); i++)
- responseFields[i] = iter.next();
+ for (Object value : descriptorMap.values())
+ responseFields[i++] = value;
} else {
for (i=0; i < fieldNames.length; i++) {
if ((fieldNames[i] == null) || (fieldNames[i].equals(""))) {
@@ -883,9 +884,9 @@ public class DescriptorSupport
* not a String with value "t", "f", "true", "false". These String
* values must not be case sensitive.
* <LI> visibility fieldName, if defined, is null, or not a
- * Numeric String or a not Numeric Value >= 1 and <= 4
+ * Numeric String or a not Numeric Value >= 1 and <= 4
* <LI> severity fieldName, if defined, is null, or not a Numeric
- * String or not a Numeric Value >= 0 and <= 6<br>
+ * String or not a Numeric Value >= 0 and <= 6<br>
* <LI> persistPolicy fieldName, if defined, is null, or not one of
* the following strings:<br>
* "OnUpdate", "OnTimer", "NoMoreOftenThan", "OnUnregister", "Always",
@@ -904,7 +905,7 @@ public class DescriptorSupport
}
// verify that the descriptor is valid, by iterating over each field...
- Set returnedSet = descriptorMap.entrySet();
+ Set<Map.Entry<String, Object>> returnedSet = descriptorMap.entrySet();
if (returnedSet == null) { // null descriptor, not valid
if (MODELMBEAN_LOGGER.isLoggable(Level.FINEST)) {
@@ -925,9 +926,7 @@ public class DescriptorSupport
// According to the descriptor type we validate the fields contained
- for (Iterator iter = returnedSet.iterator(); iter.hasNext();) {
- Map.Entry currElement = (Map.Entry) iter.next();
-
+ for (Map.Entry<String, Object> currElement : returnedSet) {
if (currElement != null) {
if (currElement.getValue() != null) {
// validate the field valued...
@@ -1083,10 +1082,9 @@ public class DescriptorSupport
*/
public synchronized String toXMLString() {
final StringBuilder buf = new StringBuilder("<Descriptor>");
- Set returnedSet = descriptorMap.entrySet();
- for (Iterator iter = returnedSet.iterator(); iter.hasNext(); ) {
- final Map.Entry currElement = (Map.Entry) iter.next();
- final String name = currElement.getKey().toString();
+ Set<Map.Entry<String, Object>> returnedSet = descriptorMap.entrySet();
+ for (Map.Entry<String, Object> currElement : returnedSet) {
+ final String name = currElement.getKey();
Object value = currElement.getValue();
String valueString = null;
/* Set valueString to non-null if and only if this is a string that
@@ -1256,7 +1254,7 @@ public class DescriptorSupport
}
final Class<?> c =
Class.forName(className, false, contextClassLoader);
- constr = c.getConstructor(new Class[] {String.class});
+ constr = c.getConstructor(new Class<?>[] {String.class});
} catch (Exception e) {
throw new XMLParseException(e,
"Cannot parse value: <" + s + ">");
--- a/src/share/classes/javax/management/modelmbean/ModelMBeanAttributeInfo.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/modelmbean/ModelMBeanAttributeInfo.java Tue Nov 11 09:07:58 2008 +0000
@@ -39,7 +39,6 @@ import java.io.ObjectStreamField;
import java.io.ObjectStreamField;
import java.lang.reflect.Method;
import java.security.AccessController;
-import java.security.PrivilegedAction;
import java.util.logging.Level;
import javax.management.Descriptor;
@@ -49,32 +48,56 @@ import javax.management.RuntimeOperation
import javax.management.RuntimeOperationsException;
/**
- * The ModelMBeanAttributeInfo object describes an attribute of the ModelMBean.
+ * <p>The ModelMBeanAttributeInfo object describes an attribute of the ModelMBean.
* It is a subclass of MBeanAttributeInfo with the addition of an associated Descriptor
- * and an implementation of the DescriptorAccess interface.
- * <P>
- * The fields in the descriptor are defined, but not limited to, the following: <P>
- * <PRE>
- * name : attribute name
- * descriptorType : must be "attribute"
- * value : current value for attribute
- * default : default value for attribute
- * displayName : name of attribute to be used in displays
- * getMethod : name of operation descriptor for get method
- * setMethod : name of operation descriptor for set method
- * protocolMap : object which implements the Descriptor interface: mappings
- * must be appropriate for the attribute
- * and entries can be updated or augmented at runtime.
- * persistPolicy : OnUpdate|OnTimer|NoMoreOftenThan|OnUnregister|Always|Never
- * persistPeriod : seconds - frequency of persist cycle. Used when persistPolicy
- * is "OnTimer" or "NoMoreOftenThan".
- * currencyTimeLimit : how long value is valid, <0 never, =0 always, >0 seconds
- * lastUpdatedTimeStamp : when value was set
- * visibility : 1-4 where 1: always visible, 4: rarely visible
- * presentationString : xml formatted string to allow presentation of data
- * </PRE>
- * The default descriptor contains the name, descriptorType and displayName fields.
- * The default value of the name and displayName fields is the name of the attribute.
+ * and an implementation of the DescriptorAccess interface.</p>
+ *
+ * <P id="descriptor">
+ * The fields in the descriptor are defined, but not limited to, the following.
+ * Note that when the Type in this table is Number, a String that is the decimal
+ * representation of a Long can also be used.</P>
+ *
+ * <table border="1" cellpadding="5">
+ * <tr><th>Name</th><th>Type</th><th>Meaning</th></tr>
+ * <tr><td>name</td><td>String</td>
+ * <td>Attribute name.</td></tr>
+ * <tr><td>descriptorType</td><td>String</td>
+ * <td>Must be "attribute".</td></tr>
+ * <tr id="value-field"><td>value</td><td>Object</td>
+ * <td>Current (cached) value for attribute.</td></tr>
+ * <tr><td>default</td><td>Object</td>
+ * <td>Default value for attribute.</td></tr>
+ * <tr><td>displayName</td><td>String</td>
+ * <td>Name of attribute to be used in displays.</td></tr>
+ * <tr><td>getMethod</td><td>String</td>
+ * <td>Name of operation descriptor for get method.</td></tr>
+ * <tr><td>setMethod</td><td>String</td>
+ * <td>Name of operation descriptor for set method.</td></tr>
+ * <tr><td>protocolMap</td><td>Descriptor</td>
+ * <td>See the section "Protocol Map Support" in the JMX specification
+ * document. Mappings must be appropriate for the attribute and entries
+ * can be updated or augmented at runtime.</td></tr>
+ * <tr><td>persistPolicy</td><td>String</td>
+ * <td>One of: OnUpdate|OnTimer|NoMoreOftenThan|OnUnregister|Always|Never.
+ * See the section "MBean Descriptor Fields" in the JMX specification
+ * document.</td></tr>
+ * <tr><td>persistPeriod</td><td>Number</td>
+ * <td>Frequency of persist cycle in seconds. Used when persistPolicy is
+ * "OnTimer" or "NoMoreOftenThan".</td></tr>
+ * <tr><td>currencyTimeLimit</td><td>Number</td>
+ * <td>How long <a href="#value=field">value</a> is valid: <0 never,
+ * =0 always, >0 seconds.</td></tr>
+ * <tr><td>lastUpdatedTimeStamp</td><td>Number</td>
+ * <td>When <a href="#value-field">value</a> was set.</td></tr>
+ * <tr><td>visibility</td><td>Number</td>
+ * <td>1-4 where 1: always visible, 4: rarely visible.</td></tr>
+ * <tr><td>presentationString</td><td>String</td>
+ * <td>XML formatted string to allow presentation of data.</td></tr>
+ * </table>
+ *
+ * <p>The default descriptor contains the name, descriptorType and displayName
+ * fields. The default value of the name and displayName fields is the name of
+ * the attribute.</p>
*
* <p><b>Note:</b> because of inconsistencies in previous versions of
* this specification, it is recommended not to use negative or zero
--- a/src/share/classes/javax/management/modelmbean/ModelMBeanConstructorInfo.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/modelmbean/ModelMBeanConstructorInfo.java Tue Nov 11 09:07:58 2008 +0000
@@ -49,22 +49,33 @@ import javax.management.RuntimeOperation
import javax.management.RuntimeOperationsException;
/**
- * The ModelMBeanConstructorInfo object describes a constructor of the ModelMBean.
+ * <p>The ModelMBeanConstructorInfo object describes a constructor of the ModelMBean.
* It is a subclass of MBeanConstructorInfo with the addition of an associated Descriptor
- * and an implementation of the DescriptorAccess interface.
- * <P>
- * <PRE>
- * The fields in the descriptor are defined, but not limited to, the following: <P>
- * name : constructor name
- * descriptorType : must be "operation"
- * role : must be "constructor"
- * displayName : human readable name of constructor
- * visibility : 1-4 where 1: always visible 4: rarely visible
- * presentationString : xml formatted string to describe how to present operation
- *</PRE>
+ * and an implementation of the DescriptorAccess interface.</p>
+ *
+ * <P id="descriptor">
+ * The fields in the descriptor are defined, but not limited to, the following.
+ * Note that when the Type in this table is Number, a String that is the decimal
+ * representation of a Long can also be used.</P>
+ *
+ * <table border="1" cellpadding="5">
+ * <tr><th>Name</th><th>Type</th><th>Meaning</th></tr>
+ * <tr><td>name</td><td>String</td>
+ * <td>Constructor name.</td></tr>
+ * <tr><td>descriptorType</td><td>String</td>
+ * <td>Must be "operation".</td></tr>
+ * <tr><td>role</td><td>String</td>
+ * <td>Must be "constructor".</td></tr>
+ * <tr><td>displayName</td><td>String</td>
+ * <td>Human readable name of constructor.</td></tr>
+ * <tr><td>visibility</td><td>Number</td>
+ * <td>1-4 where 1: always visible 4: rarely visible.</td></tr>
+ * <tr><td>presentationString</td><td>String</td>
+ * <td>XML formatted string to describe how to present operation</td></tr>
+ * </table>
*
* <p>The {@code persistPolicy} and {@code currencyTimeLimit} fields
- * are meaningless for constructors, but are not considered invalid.
+ * are meaningless for constructors, but are not considered invalid.</p>
*
* <p>The default descriptor will have the {@code name}, {@code
* descriptorType}, {@code displayName} and {@code role} fields. The
@@ -152,7 +163,7 @@ public class ModelMBeanConstructorInfo
* describing the MBean constructor.
*/
public ModelMBeanConstructorInfo(String description,
- Constructor constructorMethod)
+ Constructor<?> constructorMethod)
{
super(description, constructorMethod);
if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
@@ -194,7 +205,7 @@ public class ModelMBeanConstructorInfo
*/
public ModelMBeanConstructorInfo(String description,
- Constructor constructorMethod,
+ Constructor<?> constructorMethod,
Descriptor descriptor)
{
--- a/src/share/classes/javax/management/modelmbean/ModelMBeanInfo.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/modelmbean/ModelMBeanInfo.java Tue Nov 11 09:07:58 2008 +0000
@@ -156,29 +156,55 @@ public interface ModelMBeanInfo
/**
- * Returns the ModelMBean's descriptor which contains MBean wide policies. This descriptor contains
- * metadata about the MBean and default policies for persistence and caching.
- * <P>
- * The fields in the descriptor are defined, but not limited to, the following:
- * <PRE>
- * name : MBean name
- * descriptorType : must be "mbean"
- * displayName : name of attribute to be used in displays
- * persistPolicy : OnUpdate|OnTimer|NoMoreOftenThan|OnUnregister|Always|Never
- * persistLocation : The fully qualified directory name where the MBean should be persisted (if appropriate)
- * persistFile : File name into which the MBean should be persisted
- * persistPeriod : seconds - frequency of persist cycle for OnTime and NoMoreOftenThan PersistPolicy
- * currencyTimeLimit : how long value is valid, <0 never, =0 always, >0 seconds
- * log : where t: log all notifications f: log no notifications
- * logfile : fully qualified filename to log events to
- * visibility : 1-4 where 1: always visible 4: rarely visible
- * export : name to be used to export/expose this MBean so that it is findable by
- * other JMX Agents.
- * presentationString : xml formatted string to allow presentation of data to be associated with the MBean.
- * </PRE>
+ * <p>Returns the ModelMBean's descriptor which contains MBean wide
+ * policies. This descriptor contains metadata about the MBean and default
+ * policies for persistence and caching.</p>
+ *
+ * <P id="descriptor">
+ * The fields in the descriptor are defined, but not limited to, the
+ * following. Note that when the Type in this table is Number, a String
+ * that is the decimal representation of a Long can also be used.</P>
+ *
+ * <table border="1" cellpadding="5">
+ * <tr><th>Name</th><th>Type</th><th>Meaning</th></tr>
+ * <tr><td>name</td><td>String</td>
+ * <td>MBean name.</td></tr>
+ * <tr><td>descriptorType</td><td>String</td>
+ * <td>Must be "mbean".</td></tr>
+ * <tr><td>displayName</td><td>String</td>
+ * <td>Name of MBean to be used in displays.</td></tr>
+ * <tr><td>persistPolicy</td><td>String</td>
+ * <td>One of: OnUpdate|OnTimer|NoMoreOftenThan|OnUnregister|Always|Never.
+ * See the section "MBean Descriptor Fields" in the JMX specification
+ * document.</td></tr>
+ * <tr><td>persistLocation</td><td>String</td>
+ * <td>The fully qualified directory name where the MBean should be
+ * persisted (if appropriate).</td></tr>
+ * <tr><td>persistFile</td><td>String</td>
+ * <td>File name into which the MBean should be persisted.</td></tr>
+ * <tr><td>persistPeriod</td><td>Number</td>
+ * <td>Frequency of persist cycle in seconds, for OnTime and
+ * NoMoreOftenThan PersistPolicy</td></tr>
+ * <tr><td>currencyTimeLimit</td><td>Number</td>
+ * <td>How long cached value is valid: <0 never, =0 always,
+ * >0 seconds.</td></tr>
+ * <tr><td>log</td><td>String</td>
+ * <td>t: log all notifications, f: log no notifications.</td></tr>
+ * <tr><td>logfile</td><td>String</td>
+ * <td>Fully qualified filename to log events to.</td></tr>
+ * <tr><td>visibility</td><td>Number</td>
+ * <td>1-4 where 1: always visible 4: rarely visible.</td></tr>
+ * <tr><td>export</td><td>String</td>
+ * <td>Name to be used to export/expose this MBean so that it is
+ * findable by other JMX Agents.</td></tr>
+ * <tr><td>presentationString</td><td>String</td>
+ * <td>XML formatted string to allow presentation of data to be
+ * associated with the MBean.</td></tr>
+ * </table>
+ *
* <P>
* The default descriptor is: name=className,descriptorType="mbean", displayName=className,
- * persistPolicy="never",log="F",export="F",visibility="1"
+ * persistPolicy="never",log="F",visibility="1"
* If the descriptor does not contain all these fields, they will be added with these default values.
*
* <p><b>Note:</b> because of inconsistencies in previous versions of
@@ -207,7 +233,7 @@ public interface ModelMBeanInfo
* does a complete replacement of the descriptor, no merging is done. If the descriptor to
* set to is null then the default descriptor will be created.
* The default descriptor is: name=className,descriptorType="mbean", displayName=className,
- * persistPolicy="never",log="F",export="F",visibility="1"
+ * persistPolicy="never",log="F",visibility="1"
* If the descriptor does not contain all these fields, they will be added with these default values.
*
* See {@link #getMBeanDescriptor getMBeanDescriptor} method javadoc for description of valid field names.
--- a/src/share/classes/javax/management/modelmbean/ModelMBeanNotificationInfo.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/modelmbean/ModelMBeanNotificationInfo.java Tue Nov 11 09:07:58 2008 +0000
@@ -46,34 +46,46 @@ import javax.management.RuntimeOperation
import javax.management.RuntimeOperationsException;
/**
- * The ModelMBeanNotificationInfo object describes a notification emitted
+ * <p>The ModelMBeanNotificationInfo object describes a notification emitted
* by a ModelMBean.
* It is a subclass of MBeanNotificationInfo with the addition of an
- * associated Descriptor and an implementation of the Descriptor interface.
- * <P>
- * The fields in the descriptor are defined, but not limited to,
- * the following:
- * <PRE>
- * name : notification name
- * descriptorType : must be "notification"
- * severity : 0-6 where 0: unknown; 1: non-recoverable;
- * 2: critical, failure; 3: major, severe;
- * 4: minor, marginal, error; 5: warning;
- * 6: normal, cleared, informative
- * messageID : unique key for message text (to allow translation,
- * analysis)
- * messageText : text of notification
- * log : T - log message F - do not log message
- * logfile : string fully qualified file name appropriate for
- * operating system
- * visibility : 1-4 where 1: always visible 4: rarely visible
- * presentationString : xml formatted string to allow presentation of data
- * </PRE>
- * The default descriptor contains the name, descriptorType,
+ * associated Descriptor and an implementation of the Descriptor interface.</p>
+ *
+ * <P id="descriptor">
+ * The fields in the descriptor are defined, but not limited to, the following.
+ * Note that when the Type in this table is Number, a String that is the decimal
+ * representation of a Long can also be used.</P>
+ *
+ * <table border="1" cellpadding="5">
+ * <tr><th>Name</th><th>Type</th><th>Meaning</th></tr>
+ * <tr><td>name</td><td>String</td>
+ * <td>Notification name.</td></tr>
+ * <tr><td>descriptorType</td><td>String</td>
+ * <td>Must be "notification".</td></tr>
+ * <tr><td>severity</td><td>Number</td>
+ * <td>0-6 where 0: unknown; 1: non-recoverable;
+ * 2: critical, failure; 3: major, severe;
+ * 4: minor, marginal, error; 5: warning;
+ * 6: normal, cleared, informative</td></tr>
+ * <tr><td>messageID</td><td>String</td>
+ * <td>Unique key for message text (to allow translation, analysis).</td></tr>
+ * <tr><td>messageText</td><td>String</td>
+ * <td>Text of notification.</td></tr>
+ * <tr><td>log</td><td>String</td>
+ * <td>T - log message, F - do not log message.</td></tr>
+ * <tr><td>logfile</td><td>String</td>
+ * <td>fully qualified file name appropriate for operating system.</td></tr>
+ * <tr><td>visibility</td><td>Number</td>
+ * <td>1-4 where 1: always visible 4: rarely visible.</td></tr>
+ * <tr><td>presentationString</td><td>String</td>
+ * <td>XML formatted string to allow presentation of data.</td></tr>
+ * </table>
+ *
+ * <p>The default descriptor contains the name, descriptorType,
* displayName and severity(=6) fields. The default value of the name
* and displayName fields is the name of the Notification class (as
* specified by the <code>name</code> parameter of the
- * ModelMBeanNotificationInfo constructor).
+ * ModelMBeanNotificationInfo constructor).</p>
*
* <p>The <b>serialVersionUID</b> of this class is <code>-7445681389570207141L</code>.
*
--- a/src/share/classes/javax/management/modelmbean/ModelMBeanOperationInfo.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/modelmbean/ModelMBeanOperationInfo.java Tue Nov 11 09:07:58 2008 +0000
@@ -49,27 +49,48 @@ import javax.management.RuntimeOperation
import javax.management.RuntimeOperationsException;
/**
- * The ModelMBeanOperationInfo object describes a management operation of the ModelMBean.
- * It is a subclass of MBeanOperationInfo with the addition of an associated Descriptor
- * and an implementation of the DescriptorAccess interface.
- * <P>
- * <PRE>
- * The fields in the descriptor are defined, but not limited to, the following:
- * name : operation name
- * descriptorType : must be "operation"
- * class : class where method is defined (fully qualified)
- * role : must be "operation", "getter", or "setter
- * targetObject : object on which to execute this method
- * targetType : type of object reference for targetObject. Can be:
- * ObjectReference | Handle | EJBHandle | IOR | RMIReference.
- * value : cached value for operation
- * currencyTimeLimit : how long cached value is valid
- * lastUpdatedTimeStamp : when cached value was set
- * visibility : 1-4 where 1: always visible 4: rarely visible
- * presentationString : xml formatted string to describe how to present operation
- * </PRE>
- * The default descriptor will have name, descriptorType, displayName and role fields set.
- * The default value of the name and displayName fields is the operation name.
+ * <p>The ModelMBeanOperationInfo object describes a management operation of
+ * the ModelMBean. It is a subclass of MBeanOperationInfo with the addition
+ * of an associated Descriptor and an implementation of the DescriptorAccess
+ * interface.</p>
+ *
+ * <P id="descriptor">
+ * The fields in the descriptor are defined, but not limited to, the following.
+ * Note that when the Type in this table is Number, a String that is the decimal
+ * representation of a Long can also be used.</P>
+ *
+ * <table border="1" cellpadding="5">
+ * <tr><th>Name</th><th>Type</th><th>Meaning</th></tr>
+ * <tr><td>name</td><td>String</td>
+ * <td>Operation name.</td></tr>
+ * <tr><td>descriptorType</td><td>String</td>
+ * <td>Must be "operation".</td></tr>
+ * <tr><td>class</td><td>String</td>
+ * <td>Class where method is defined (fully qualified).</td></tr>
+ * <tr><td>role</td><td>String</td>
+ * <td>Must be "operation", "getter", or "setter".</td></tr>
+ * <tr><td>targetObject</td><td>Object</td>
+ * <td>Object on which to execute this method.</td></tr>
+ * <tr><td>targetType</td><td>String</td>
+ * <td>type of object reference for targetObject. Can be:
+ * ObjectReference | Handle | EJBHandle | IOR | RMIReference.</td></tr>
+ * <tr><td>value</td><td>Object</td>
+ * <td>Cached value for operation.</td></tr>
+ * <tr><td>displayName</td><td>String</td>
+ * <td>Human readable display name of the operation.</td>
+ * <tr><td>currencyTimeLimit</td><td>Number</td>
+ * <td>How long cached value is valid.</td></tr>
+ * <tr><td>lastUpdatedTimeStamp</td><td>Number</td>
+ * <td>When cached value was set.</td></tr>
+ * <tr><td>visibility</td><td>Number</td>
+ * <td>1-4 where 1: always visible 4: rarely visible.</td></tr>
+ * <tr><td>presentationString</td><td>String</td>
+ * <td>XML formatted string to describe how to present operation</td></tr>
+ * </table>
+ *
+ * <p>The default descriptor will have name, descriptorType, displayName and
+ * role fields set. The default value of the name and displayName fields is
+ * the operation name.</p>
*
* <p><b>Note:</b> because of inconsistencies in previous versions of
* this specification, it is recommended not to use negative or zero
--- a/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java Tue Nov 11 09:07:58 2008 +0000
@@ -1074,7 +1074,7 @@ public class RequiredModelMBean
}
}
- final Class targetClass;
+ final Class<?> targetClass;
if (opClassName != null) {
try {
@@ -1126,20 +1126,20 @@ public class RequiredModelMBean
"resolving " + targetClass.getName() + "." + opMethodName);
}
- final Class[] argClasses;
+ final Class<?>[] argClasses;
if (sig == null)
argClasses = null;
else {
final ClassLoader targetClassLoader = targetClass.getClassLoader();
- argClasses = new Class[sig.length];
+ argClasses = new Class<?>[sig.length];
for (int i = 0; i < sig.length; i++) {
if (tracing) {
MODELMBEAN_LOGGER.logp(Level.FINER,
RequiredModelMBean.class.getName(),"resolveMethod",
"resolve type " + sig[i]);
}
- argClasses[i] = (Class) primitiveClassMap.get(sig[i]);
+ argClasses[i] = (Class<?>) primitiveClassMap.get(sig[i]);
if (argClasses[i] == null) {
try {
argClasses[i] =
@@ -1170,7 +1170,7 @@ public class RequiredModelMBean
/* Map e.g. "int" to int.class. Goodness knows how many time this
particular wheel has been reinvented. */
- private static final Class[] primitiveClasses = {
+ private static final Class<?>[] primitiveClasses = {
int.class, long.class, boolean.class, double.class,
float.class, short.class, byte.class, char.class,
};
@@ -1178,7 +1178,7 @@ public class RequiredModelMBean
new HashMap<String,Class<?>>();
static {
for (int i = 0; i < primitiveClasses.length; i++) {
- final Class c = primitiveClasses[i];
+ final Class<?> c = primitiveClasses[i];
primitiveClassMap.put(c.getName(), c);
}
}
@@ -1645,7 +1645,7 @@ public class RequiredModelMBean
try {
ClassLoader cl =
response.getClass().getClassLoader();
- Class c = Class.forName(respType, true, cl);
+ Class<?> c = Class.forName(respType, true, cl);
subtype = c.isInstance(response);
} catch (Exception e) {
subtype = false;
@@ -1904,7 +1904,7 @@ public class RequiredModelMBean
if (attrSetMethod == null) {
if (attrValue != null) {
try {
- final Class clazz = loadClass(attrType);
+ final Class<?> clazz = loadClass(attrType);
if (! clazz.isInstance(attrValue)) throw new
InvalidAttributeValueException(clazz.getName() +
" expected, " +
@@ -2044,8 +2044,7 @@ public class RequiredModelMBean
final AttributeList responseList = new AttributeList();
// Go through the list of attributes
- for (Iterator i = attributes.iterator(); i.hasNext();) {
- final Attribute attr = (Attribute) i.next();
+ for (Attribute attr : attributes.asList()) {
try {
setAttribute(attr);
responseList.add(attr);
@@ -2799,7 +2798,7 @@ public class RequiredModelMBean
return MBeanServerFactory.getClassLoaderRepository(server);
}
- private Class loadClass(String className)
+ private Class<?> loadClass(String className)
throws ClassNotFoundException {
try {
return Class.forName(className);
--- a/src/share/classes/javax/management/namespace/JMXNamespaces.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/namespace/JMXNamespaces.java Tue Nov 11 09:07:58 2008 +0000
@@ -26,21 +26,19 @@ package javax.management.namespace;
package javax.management.namespace;
import com.sun.jmx.defaults.JmxProperties;
-import com.sun.jmx.namespace.JMXNamespaceUtils;
import com.sun.jmx.namespace.ObjectNameRouter;
import com.sun.jmx.namespace.serial.RewritingProcessor;
import com.sun.jmx.namespace.RoutingConnectionProxy;
import com.sun.jmx.namespace.RoutingServerProxy;
-import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
+import javax.management.InstanceNotFoundException;
import javax.management.MBeanServer;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
-import javax.management.remote.JMXConnector;
/**
* Static constants and utility methods to help work with
@@ -69,23 +67,6 @@ public class JMXNamespaces {
/**
- * Returns a connector connected to a sub name space exposed through
- * the parent connector.
- * @param parent the parent connector.
- * @param namespace the {@linkplain javax.management.namespace name space}
- * to which the returned connector is
- * connected.
- * @return A connector connected to a sub name space exposed through
- * the parent connector.
- **/
- public static JMXConnector narrowToNamespace(final JMXConnector parent,
- final String namespace)
- throws IOException {
-
- return JMXNamespaceUtils.cd(parent,namespace,true);
- }
-
- /**
* Creates a new {@code MBeanServerConnection} proxy on a
* {@linkplain javax.management.namespace sub name space}
* of the given parent.
@@ -96,15 +77,18 @@ public class JMXNamespaces {
* name space} in which to narrow.
* @return A new {@code MBeanServerConnection} proxy that shows the content
* of that name space.
- * @throws IllegalArgumentException if the name space does not exist, or
- * if a proxy for that name space cannot be created.
+ * @throws IllegalArgumentException if either argument is null,
+ * or the name space does not exist, or if a proxy for that name space
+ * cannot be created. The {@linkplain Throwable#getCause() cause} of
+ * this exception will be an {@link InstanceNotFoundException} if and only
+ * if the name space is found not to exist.
*/
public static MBeanServerConnection narrowToNamespace(
MBeanServerConnection parent,
String namespace) {
if (LOG.isLoggable(Level.FINER))
LOG.finer("Making MBeanServerConnection for: " +namespace);
- return RoutingConnectionProxy.cd(parent,namespace);
+ return RoutingConnectionProxy.cd(parent, namespace, true);
}
/**
@@ -120,13 +104,15 @@ public class JMXNamespaces {
* of that name space.
* @throws IllegalArgumentException if either argument is null,
* or the name space does not exist, or if a proxy for that name space
- * cannot be created.
+ * cannot be created. The {@linkplain Throwable#getCause() cause} of
+ * this exception will be an {@link InstanceNotFoundException} if and only
+ * if the name space is found not to exist.
*/
public static MBeanServer narrowToNamespace(MBeanServer parent,
String namespace) {
if (LOG.isLoggable(Level.FINER))
- LOG.finer("Making NamespaceServerProxy for: " +namespace);
- return RoutingServerProxy.cd(parent,namespace);
+ LOG.finer("Making MBeanServer for: " +namespace);
+ return RoutingServerProxy.cd(parent, namespace, true);
}
/**
@@ -266,7 +252,7 @@ public class JMXNamespaces {
ObjectNameRouter.normalizeNamespacePath(namespace,false,
true,false);
try {
- // We could use Util.newObjectName here - but throwing an
+ // We could use ObjectName.valueOf here - but throwing an
// IllegalArgumentException that contains just the supplied
// namespace instead of the whole ObjectName seems preferable.
return ObjectName.getInstance(sourcePath+
--- a/src/share/classes/javax/management/namespace/JMXRemoteNamespace.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/namespace/JMXRemoteNamespace.java Tue Nov 11 09:07:58 2008 +0000
@@ -27,10 +27,10 @@ package javax.management.namespace;
import com.sun.jmx.defaults.JmxProperties;
import com.sun.jmx.mbeanserver.Util;
-import com.sun.jmx.namespace.JMXNamespaceUtils;
import com.sun.jmx.remote.util.EnvHelp;
import java.io.IOException;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
@@ -39,6 +39,7 @@ import java.util.logging.Logger;
import javax.management.AttributeChangeNotification;
+import javax.management.ClientContext;
import javax.management.InstanceNotFoundException;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanNotificationInfo;
@@ -220,15 +221,24 @@ public class JMXRemoteNamespace
initParentOnce(this);
// URL must not be null.
- this.jmxURL = JMXNamespaceUtils.checkNonNull(sourceURL,"url");
+ if (sourceURL == null)
+ throw new IllegalArgumentException("Null URL");
+ this.jmxURL = sourceURL;
this.broadcaster =
new NotificationBroadcasterSupport(connectNotification);
// handles options
- this.optionsMap = JMXNamespaceUtils.unmodifiableMap(optionsMap);
+ this.optionsMap = unmodifiableMap(optionsMap);
// handles (dis)connection events
this.listener = new ConnectionListener();
+ }
+
+ // returns un unmodifiable view of a map.
+ private static <K,V> Map<K,V> unmodifiableMap(Map<K,V> aMap) {
+ if (aMap == null || aMap.isEmpty())
+ return Collections.emptyMap();
+ return Collections.unmodifiableMap(aMap);
}
/**
@@ -483,106 +493,171 @@ public class JMXRemoteNamespace
}
}
- JMXConnector connect(JMXServiceURL url, Map<String,?> env)
+ private JMXConnector connect(JMXServiceURL url, Map<String,?> env)
throws IOException {
- final JMXConnector c = newJMXConnector(jmxURL, env);
+ final JMXConnector c = newJMXConnector(url, env);
c.connect(env);
return c;
}
/**
- * Creates a new JMXConnector with the specified {@code url} and
- * {@code env} options map.
- * <p>
- * This method first calls {@link JMXConnectorFactory#newJMXConnector
- * JMXConnectorFactory.newJMXConnector(jmxURL, env)} to obtain a new
- * JMX connector, and returns that.
- * </p>
- * <p>
- * A subclass of {@link JMXRemoteNamespace} can provide an implementation
- * that connects to a sub namespace of the remote server by subclassing
- * this class in the following way:
- * <pre>
- * class JMXRemoteSubNamespace extends JMXRemoteNamespace {
- * private final String subnamespace;
- * JMXRemoteSubNamespace(JMXServiceURL url,
- * Map{@code <String,?>} env, String subnamespace) {
- * super(url,options);
- * this.subnamespace = subnamespace;
- * }
- * protected JMXConnector newJMXConnector(JMXServiceURL url,
- * Map<String,?> env) throws IOException {
- * final JMXConnector inner = super.newJMXConnector(url,env);
- * return {@link JMXNamespaces#narrowToNamespace(JMXConnector,String)
- * JMXNamespaces.narrowToNamespace(inner,subnamespace)};
- * }
- * }
- * </pre>
- * </p>
- * <p>
- * Some connectors, like the JMXMP connector server defined by the
- * version 1.2 of the JMX API may not have been upgraded to use the
- * new {@linkplain javax.management.event Event Service} defined in this
- * version of the JMX API.
- * <p>
- * In that case, and if the remote server to which this JMXRemoteNamespace
- * connects also contains namespaces, it may be necessary to configure
- * explicitly an {@linkplain
- * javax.management.event.EventClientDelegate#newForwarder()
- * Event Client Forwarder} on the remote server side, and to force the use
- * of an {@link EventClient} on this client side.
- * <br>
- * A subclass of {@link JMXRemoteNamespace} can provide an implementation
- * of {@code newJMXConnector} that will force notification subscriptions
- * to flow through an {@link EventClient} over a legacy protocol by
- * overriding this method in the following way:
- * </p>
- * <pre>
- * class JMXRemoteEventClientNamespace extends JMXRemoteNamespace {
- * JMXRemoteSubNamespaceConnector(JMXServiceURL url,
- * Map<String,?> env) {
- * super(url,options);
- * }
- * protected JMXConnector newJMXConnector(JMXServiceURL url,
- * Map<String,?> env) throws IOException {
- * final JMXConnector inner = super.newJMXConnector(url,env);
- * return {@link EventClient#withEventClient(
- * JMXConnector) EventClient.withEventClient(inner)};
- * }
- * }
- * </pre>
- * <p>
- * Note that the remote server also needs to provide an {@link
- * javax.management.event.EventClientDelegateMBean}: only configuring
- * the client side (this object) is not enough.<br>
- * In summary, this technique should be used if the remote server
- * supports JMX namespaces, but uses a JMX Connector Server whose
- * implementation does not transparently use the new Event Service
- * (as would be the case with the JMXMPConnectorServer implementation
- * from the reference implementation of the JMX Remote API 1.0
- * specification).
- * </p>
+ * <p>Creates a new JMXConnector with the specified {@code url} and
+ * {@code env} options map. The default implementation of this method
+ * returns {@link JMXConnectorFactory#newJMXConnector
+ * JMXConnectorFactory.newJMXConnector(jmxURL, env)}. Subclasses can
+ * override this method to customize behavior.</p>
+ *
* @param url The JMXServiceURL of the remote server.
- * @param optionsMap An unmodifiable options map that will be passed to the
+ * @param optionsMap An options map that will be passed to the
* {@link JMXConnectorFactory} when {@linkplain
* JMXConnectorFactory#newJMXConnector creating} the
* {@link JMXConnector} that can connect to the remote source
* MBean Server.
- * @return An unconnected JMXConnector to use to connect to the remote
- * server
- * @throws java.io.IOException if the connector could not be created.
+ * @return A JMXConnector to use to connect to the remote server
+ * @throws IOException if the connector could not be created.
* @see JMXConnectorFactory#newJMXConnector(javax.management.remote.JMXServiceURL, java.util.Map)
* @see #JMXRemoteNamespace
*/
protected JMXConnector newJMXConnector(JMXServiceURL url,
Map<String,?> optionsMap) throws IOException {
- final JMXConnector c =
- JMXConnectorFactory.newJMXConnector(jmxURL, optionsMap);
-// TODO: uncomment this when contexts are added
-// return ClientContext.withDynamicContext(c);
- return c;
- }
-
+ return JMXConnectorFactory.newJMXConnector(jmxURL, optionsMap);
+ }
+
+ /**
+ * <p>Called when a new connection is established using {@link #connect}
+ * so that subclasses can customize the connection. The default
+ * implementation of this method effectively does the following:</p>
+ *
+ * <pre>
+ * MBeanServerConnection mbsc = {@link JMXConnector#getMBeanServerConnection()
+ * jmxc.getMBeanServerConnection()};
+ * try {
+ * return {@link ClientContext#withDynamicContext
+ * ClientContext.withDynamicContext(mbsc)};
+ * } catch (IllegalArgumentException e) {
+ * return mbsc;
+ * }
+ * </pre>
+ *
+ * <p>In other words, it arranges for the client context to be forwarded
+ * to the remote MBean Server if the remote MBean Server supports contexts;
+ * otherwise it ignores the client context.</p>
+ *
+ * <h4>Example: connecting to a remote namespace</h4>
+ *
+ * <p>A subclass that wanted to narrow into a namespace of
+ * the remote MBeanServer might look like this:</p>
+ *
+ * <pre>
+ * class JMXRemoteSubNamespace extends JMXRemoteNamespace {
+ * private final String subnamespace;
+ *
+ * JMXRemoteSubNamespace(
+ * JMXServiceURL url, Map{@code <String, ?>} env, String subnamespace) {
+ * super(url, env);
+ * this.subnamespace = subnamespace;
+ * }
+ *
+ * {@code @Override}
+ * protected MBeanServerConnection getMBeanServerConnection(
+ * JMXConnector jmxc) throws IOException {
+ * MBeanServerConnection mbsc = super.getMBeanServerConnection(jmxc);
+ * return {@link JMXNamespaces#narrowToNamespace(MBeanServerConnection,String)
+ * JMXNamespaces.narrowToNamespace(mbsc, subnamespace)};
+ * }
+ * }
+ * </pre>
+ *
+ * <h4>Example: using the Event Service for notifications</h4>
+ *
+ * <p>Some connectors may have been designed to work with an earlier
+ * version of the JMX API, and may not have been upgraded to use
+ * the {@linkplain javax.management.event Event Service} defined in
+ * this version of the JMX API. In that case, and if the remote
+ * server to which this JMXRemoteNamespace connects also contains
+ * namespaces, it may be necessary to configure explicitly an {@linkplain
+ * javax.management.event.EventClientDelegate#newForwarder Event Client
+ * Forwarder} on the remote server side, and to force the use of an {@link
+ * EventClient} on this client side.</p>
+ *
+ * <p>A subclass of {@link JMXRemoteNamespace} can provide an
+ * implementation of {@code getMBeanServerConnection} that will force
+ * notification subscriptions to flow through an {@link EventClient} over
+ * a legacy protocol. It can do so by overriding this method in the
+ * following way:</p>
+ *
+ * <pre>
+ * class JMXRemoteEventClientNamespace extends JMXRemoteNamespace {
+ * JMXRemoteEventClientNamespace(JMXServiceURL url, {@code Map<String,?>} env) {
+ * super(url, env);
+ * }
+ *
+ * {@code @Override}
+ * protected MBeanServerConnection getMBeanServerConnection(JMXConnector jmxc)
+ * throws IOException {
+ * MBeanServerConnection mbsc = super.getMBeanServerConnection(jmxc);
+ * return EventClient.getEventClientConnection(mbsc);
+ * }
+ * }
+ * </pre>
+ *
+ * <p>
+ * Note that the remote server also needs to provide an {@link
+ * javax.management.event.EventClientDelegateMBean}: configuring only
+ * the client side (this object) is not enough.</p>
+ *
+ * <p>In summary, this technique should be used if the remote server
+ * supports JMX namespaces, but uses a JMX Connector Server whose
+ * implementation does not transparently use the new Event Service
+ * (as would be the case with the JMXMPConnectorServer implementation
+ * from the reference implementation of the JMX Remote API 1.0
+ * specification).</p>
+ *
+ * @param jmxc the newly-created {@code JMXConnector}.
+ *
+ * @return an {@code MBeanServerConnection} connected to the remote
+ * MBeanServer.
+ *
+ * @throws IOException if the connection cannot be made. If this method
+ * throws {@code IOException} then the calling {@link #connect()} method
+ * will also fail with an {@code IOException}.
+ *
+ * @see #connect
+ */
+ protected MBeanServerConnection getMBeanServerConnection(JMXConnector jmxc)
+ throws IOException {
+ final MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
+ try {
+ return ClientContext.withDynamicContext(mbsc);
+ } catch (IllegalArgumentException e) {
+ LOG.log(Level.FINER, "ClientContext.withDynamicContext", e);
+ return mbsc;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>The sequence of events when this method is called includes,
+ * effectively, the following code:</p>
+ *
+ * <pre>
+ * JMXServiceURL url = {@link #getJMXServiceURL getJMXServiceURL}();
+ * JMXConnector jmxc = {@link #newJMXConnector newJMXConnector}(url, env);
+ * jmxc.connect();
+ * MBeanServerConnection mbsc = {@link #getMBeanServerConnection(JMXConnector)
+ * getMBeanServerConnection}(jmxc);
+ * </pre>
+ *
+ * <p>Here, {@code env} is a {@code Map} containing the entries from the
+ * {@code optionsMap} that was passed to the {@linkplain #JMXRemoteNamespace
+ * constructor} or to the {@link #newJMXRemoteNamespace newJMXRemoteNamespace}
+ * factory method.</p>
+ *
+ * <p>Subclasses can customize connection behavior by overriding the
+ * {@code getJMXServiceURL}, {@code newJMXConnector}, or
+ * {@code getMBeanServerConnection} methods.</p>
+ */
public void connect() throws IOException {
LOG.fine("connecting...");
final Map<String,Object> env =
@@ -590,7 +665,7 @@ public class JMXRemoteNamespace
try {
// XXX: We should probably document this...
// This allows to specify a loader name - which will be
- // retrieved from the paret MBeanServer.
+ // retrieved from the parent MBeanServer.
defaultClassLoader =
EnvHelp.resolveServerClassLoader(env,getMBeanServer());
} catch (InstanceNotFoundException x) {
@@ -604,7 +679,7 @@ public class JMXRemoteNamespace
final JMXConnector aconn = connect(url,env);
final MBeanServerConnection msc;
try {
- msc = aconn.getMBeanServerConnection();
+ msc = getMBeanServerConnection(aconn);
aconn.addConnectionNotificationListener(listener,null,aconn);
} catch (IOException io) {
close(aconn);
--- a/src/share/classes/javax/management/namespace/MBeanServerSupport.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/namespace/MBeanServerSupport.java Tue Nov 11 09:07:58 2008 +0000
@@ -457,7 +457,11 @@ public abstract class MBeanServerSupport
* All the various flavors of {@code MBeanServer.createMBean} methods
* will eventually call this method. A subclass that wishes to
* support MBean creation through {@code createMBean} thus only
- * needs to provide an implementation for this one method.
+ * needs to provide an implementation for this one method.</p>
+ *
+ * <p>A subclass implementation of this method should respect the contract
+ * of the various {@code createMBean} methods in the {@link MBeanServer}
+ * interface, in particular as regards exception wrapping.</p>
*
* @param className The class name of the MBean to be instantiated.
* @param name The object name of the MBean. May be null.
@@ -488,6 +492,17 @@ public abstract class MBeanServerSupport
* <CODE>preRegister</CODE> (<CODE>MBeanRegistration</CODE>
* interface) method of the MBean has thrown an exception. The
* MBean will not be registered.
+ * @exception RuntimeMBeanException If the MBean's constructor or its
+ * {@code preRegister} or {@code postRegister} method threw
+ * a {@code RuntimeException}. If the <CODE>postRegister</CODE>
+ * (<CODE>MBeanRegistration</CODE> interface) method of the MBean throws a
+ * <CODE>RuntimeException</CODE>, the <CODE>createMBean</CODE> method will
+ * throw a <CODE>RuntimeMBeanException</CODE>, although the MBean creation
+ * and registration succeeded. In such a case, the MBean will be actually
+ * registered even though the <CODE>createMBean</CODE> method
+ * threw an exception. Note that <CODE>RuntimeMBeanException</CODE> can
+ * also be thrown by <CODE>preRegister</CODE>, in which case the MBean
+ * will not be registered.
* @exception MBeanException The constructor of the MBean has
* thrown an exception
* @exception NotCompliantMBeanException This class is not a JMX
@@ -1096,7 +1111,7 @@ public abstract class MBeanServerSupport
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException {
try {
- return safeCreateMBean(className, name, null, params, signature, true);
+ return createMBean(className, name, null, params, signature, true);
} catch (InstanceNotFoundException ex) {
// should not happen!
throw new MBeanException(ex, "Unexpected exception: " + ex);
@@ -1113,7 +1128,7 @@ public abstract class MBeanServerSupport
throws ReflectionException, InstanceAlreadyExistsException,
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException, InstanceNotFoundException {
- return safeCreateMBean(className, name, loaderName, params, signature, false);
+ return createMBean(className, name, loaderName, params, signature, false);
}
/**
@@ -1126,7 +1141,7 @@ public abstract class MBeanServerSupport
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException {
try {
- return safeCreateMBean(className, name, null, null, null, true);
+ return createMBean(className, name, null, null, null, true);
} catch (InstanceNotFoundException ex) {
// should not happen!
throw new MBeanException(ex, "Unexpected exception: " + ex);
@@ -1143,32 +1158,7 @@ public abstract class MBeanServerSupport
throws ReflectionException, InstanceAlreadyExistsException,
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException, InstanceNotFoundException {
- return safeCreateMBean(className, name, loaderName, null, null, false);
- }
-
- // make sure all exceptions are correctly wrapped in a JMXException
- private ObjectInstance safeCreateMBean(String className,
- ObjectName name, ObjectName loaderName, Object[] params,
- String[] signature, boolean useRepository)
- throws ReflectionException, InstanceAlreadyExistsException,
- MBeanRegistrationException, MBeanException,
- NotCompliantMBeanException, InstanceNotFoundException {
- try {
- return createMBean(className, name, loaderName, params,
- signature, useRepository);
- } catch (ReflectionException x) { throw x;
- } catch (InstanceAlreadyExistsException x) { throw x;
- } catch (MBeanRegistrationException x) { throw x;
- } catch (MBeanException x) { throw x;
- } catch (NotCompliantMBeanException x) { throw x;
- } catch (InstanceNotFoundException x) { throw x;
- } catch (SecurityException x) { throw x;
- } catch (JMRuntimeException x) { throw x;
- } catch (RuntimeException x) {
- throw new RuntimeOperationsException(x, x.toString());
- } catch (Exception x) {
- throw new MBeanException(x, x.toString());
- }
+ return createMBean(className, name, loaderName, null, null, false);
}
--- a/src/share/classes/javax/management/openmbean/ArrayType.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/openmbean/ArrayType.java Tue Nov 11 09:07:58 2008 +0000
@@ -296,7 +296,7 @@ public class ArrayType<T> extends OpenTy
// Check and construct state specific to ArrayType
//
if (elementType.isArray()) {
- ArrayType at = (ArrayType) elementType;
+ ArrayType<?> at = (ArrayType<?>) elementType;
this.dimension = at.getDimension() + dimension;
this.elementType = at.getElementOpenType();
this.primitiveArray = at.isPrimitiveArray();
@@ -384,7 +384,7 @@ public class ArrayType<T> extends OpenTy
/* Package-private constructor for callers we trust to get it right. */
ArrayType(String className, String typeName, String description,
- int dimension, OpenType elementType,
+ int dimension, OpenType<?> elementType,
boolean primitiveArray) {
super(className, typeName, description, true);
this.dimension = dimension;
@@ -397,7 +397,7 @@ public class ArrayType<T> extends OpenTy
throws OpenDataException {
boolean isPrimitiveArray = false;
if (elementType.isArray()) {
- isPrimitiveArray = ((ArrayType) elementType).isPrimitiveArray();
+ isPrimitiveArray = ((ArrayType<?>) elementType).isPrimitiveArray();
}
return buildArrayClassName(dimension, elementType, isPrimitiveArray);
}
@@ -443,7 +443,7 @@ public class ArrayType<T> extends OpenTy
throws OpenDataException {
boolean isPrimitiveArray = false;
if (elementType.isArray()) {
- isPrimitiveArray = ((ArrayType) elementType).isPrimitiveArray();
+ isPrimitiveArray = ((ArrayType<?>) elementType).isPrimitiveArray();
}
return buildArrayDescription(dimension, elementType, isPrimitiveArray);
}
@@ -453,7 +453,7 @@ public class ArrayType<T> extends OpenTy
boolean isPrimitiveArray)
throws OpenDataException {
if (elementType.isArray()) {
- ArrayType at = (ArrayType) elementType;
+ ArrayType<?> at = (ArrayType<?>) elementType;
dimension += at.getDimension();
elementType = at.getElementOpenType();
isPrimitiveArray = at.isPrimitiveArray();
@@ -551,7 +551,7 @@ public class ArrayType<T> extends OpenTy
return false;
}
- Class objClass = obj.getClass();
+ Class<?> objClass = obj.getClass();
String objClassName = objClass.getName();
// if obj is not an array, return false
@@ -636,8 +636,8 @@ public class ArrayType<T> extends OpenTy
}
@Override
- boolean isAssignableFrom(OpenType ot) {
- if (!(ot instanceof ArrayType))
+ boolean isAssignableFrom(OpenType<?> ot) {
+ if (!(ot instanceof ArrayType<?>))
return false;
ArrayType<?> at = (ArrayType<?>) ot;
return (at.getDimension() == getDimension() &&
@@ -675,9 +675,9 @@ public class ArrayType<T> extends OpenTy
// if obj is not an ArrayType, return false
//
- if (!(obj instanceof ArrayType))
+ if (!(obj instanceof ArrayType<?>))
return false;
- ArrayType other = (ArrayType) obj;
+ ArrayType<?> other = (ArrayType<?>) obj;
// if other's dimension is different than this instance's, return false
//
@@ -879,6 +879,7 @@ public class ArrayType<T> extends OpenTy
// Build primitive array
//
try {
+ @SuppressWarnings("rawtypes")
ArrayType at = new ArrayType(simpleType, true);
if (n > 1)
at = new ArrayType<T>(n - 1, at);
@@ -934,7 +935,7 @@ public class ArrayType<T> extends OpenTy
}
}
- private ArrayType convertFromWrapperToPrimitiveTypes() {
+ private <T> ArrayType<T> convertFromWrapperToPrimitiveTypes() {
String cn = getClassName();
String tn = getTypeName();
String d = getDescription();
@@ -952,8 +953,8 @@ public class ArrayType<T> extends OpenTy
break;
}
}
- return new ArrayType(cn, tn, d,
- dimension, elementType, primitiveArray);
+ return new ArrayType<T>(cn, tn, d,
+ dimension, elementType, primitiveArray);
}
/**
@@ -1002,7 +1003,7 @@ public class ArrayType<T> extends OpenTy
}
}
- private ArrayType convertFromPrimitiveToWrapperTypes() {
+ private <T> ArrayType<T> convertFromPrimitiveToWrapperTypes() {
String cn = getClassName();
String tn = getTypeName();
String d = getDescription();
@@ -1020,7 +1021,7 @@ public class ArrayType<T> extends OpenTy
break;
}
}
- return new ArrayType(cn, tn, d,
- dimension, elementType, primitiveArray);
+ return new ArrayType<T>(cn, tn, d,
+ dimension, elementType, primitiveArray);
}
}
--- a/src/share/classes/javax/management/openmbean/CompositeDataInvocationHandler.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/openmbean/CompositeDataInvocationHandler.java Tue Nov 11 09:07:58 2008 +0000
@@ -236,8 +236,8 @@ public class CompositeDataInvocationHand
if (other == null)
return false;
- final Class proxyClass = proxy.getClass();
- final Class otherClass = other.getClass();
+ final Class<?> proxyClass = proxy.getClass();
+ final Class<?> otherClass = other.getClass();
if (proxyClass != otherClass)
return false;
InvocationHandler otherih = Proxy.getInvocationHandler(other);
--- a/src/share/classes/javax/management/openmbean/CompositeDataSupport.java Tue Nov 11 08:59:43 2008 +0000
+++ b/src/share/classes/javax/management/openmbean/CompositeDataSupport.java Tue Nov 11 09:07:58 2008 +0000
@@ -33,12 +33,14 @@ import java.util.Arrays;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
// jmx import
+import java.util.TreeSet;
//
@@ -60,16 +62,15 @@ public class CompositeDataSupport
* respective values.
* A {@link SortedMap} is used for faster retrieval of elements.
*/
- private SortedMap<String, Object> contents = new TreeMap<String, Object>();
+ private final SortedMap<String, Object> contents;
/**
* @serial The <i>composite type </i> of this <i>composite data</i> instance.
*/
- private CompositeType compositeType;
-
- /**
- * <p>
- * Constructs a <tt>CompositeDataSupport</tt> instance with the specified
+ private final CompositeType compositeType;
+
+ /**
+ * <p>Constructs a <tt>CompositeDataSupport</tt> instance with the specified
* <tt>compositeType</tt>, whose item values
* are specified by <tt>itemValues[]</tt>, in the same order as in
* <tt>itemNames[]</tt>.
@@ -79,41 +80,124 @@ public class CompositeDataSupport
* The items contained in this <tt>CompositeDataSupport</tt> instance are
* internally stored in a <tt>TreeMap</tt>,
* thus sorted in ascending lexicographic order of their names, for faster
- * retrieval of individual item values.
- * <p>
- * The constructor checks that all the constraints listed below for each
+ * retrieval of individual item values.</p>
+ *
+ * <p>The constructor checks that all the constraints listed below for each
* parameter are satisfied,
- * and throws the appropriate exception if they are not.
- * <p>
- * @param compositeType the <i>composite type </i> of this <i>composite
- * data</i> instance;
+ * and throws the appropriate exception if they are not.</p>
+ *
+ * @param compositeType the <i>composite type </i> of this <i>composite
+ * data</i> instance; must not be null.
+ *
+ * @param itemNames <tt>itemNames</tt> must list, in any order, all the
+ * item names defined in <tt>compositeType</tt>; the order in which the
+ * names are listed, is used to match values in <tt>itemValues[]</tt>; must
+ * not be null.
+ *
+ * @param itemValues the values of the items, listed in the same order as
+ * their respective names in <tt>itemNames</tt>; each item value can be
+ * null, but if it is non-null it must be a valid value for the open type
+ * defined in <tt>compositeType</tt> for the corresponding item; must be of
+ * the same size as <tt>itemNames</tt>; must not be null.
+ *
+ * @throws IllegalArgumentException <tt>compositeType</tt> is null, or
+ * <tt>itemNames[]</tt> or <tt>itemValues[]</tt> is null or empty, or one
+ * of the elements in <tt>itemNames[]</tt> is a null or empty string, or
+ * <tt>itemNames[]</tt> and <tt>itemValues[]</tt> are not of the same size.
+ *
+ * @throws OpenDataException <tt>itemNames[]</tt> or
+ * <tt>itemValues[]</tt>'s size differs from the number of items defined in
+ * <tt>compositeType</tt>, or one of the elements in <tt>itemNames[]</tt>
+ * does not exist as an item name defined in <tt>compositeType</tt>, or one
+ * of the elements in <tt>itemValues[]</tt> is not a valid value for the
+ * corresponding item as defined in <tt>compositeType</tt>.
+ */
+ public CompositeDataSupport(
+ CompositeType compositeType, String[] itemNames, Object[] itemValues)
+ throws OpenDataException {
+ this(makeMap(itemNames, itemValues), compositeType);
+ }
+
+ private static SortedMap<String, Object> makeMap(
+ String[] itemNames, Object[] itemValues)
+ throws OpenDataException {
+
+ if (itemNames == null || itemValues == null)
+ throw new IllegalArgumentException("Null itemNames or itemValues");
+ if (itemNames.length != itemValues.length) {
+ throw new IllegalArgumentException(
+ "Different lengths: itemNames[" + itemNames.length +
+ "], itemValues[" + itemValues.length + "]");
+ }
+
+ SortedMap<String, Object> map = new TreeMap<String, Object>();
+ for (int i = 0; i < itemNames.length; i++) {
+ String name = itemNames[i];
+ if (name == null || name.equals(""))
+ throw new IllegalArgumentException("Null or empty item name");
+ if (map.containsKey(name))
+ throw new OpenDataException("Duplicate item name " + name);
+ map.put(itemNames[i], itemValues[i]);
+ }
+
+ return map;
+ }
+
+ /**
+ * <p>
+ * Constructs a <tt>CompositeDataSupport</tt> instance with the specified <tt>compositeType</tt>, whose item names and corresponding values
+ * are given by the mappings in the map <tt>items</tt>.
+ * This constructor converts the keys to a string array and the values to an object array and calls
+ * <tt>CompositeDataSupport(javax.management.openmbean.CompositeType, java.lang.String[], java.lang.Object[])</tt>.
+ *
+ * @param compositeType the <i>composite type </i> of this <i>composite data</i> instance;
* must not be null.
- * <p>
- * @param itemNames <tt>itemNames</tt> must list, in any order, all the
- * item names defined in <tt>compositeType</tt>;
- * the order in which the names are listed, is used to
- * match values in <tt>itemValues[]</tt>;
- * must not be null or empty.
- * <p>
- * @param itemValues the values of the items, listed in the same order as
- * their respective names in <tt>itemNames</tt>;
- * each item value can be null, but if it is non-null it must be
- * a valid value for the open type defined in <tt>compositeType</tt> for the corresponding item;
- * must be of the same size as <tt>itemNames</tt>; must not be null or empty.
- * <p>
- * @throws IllegalArgumentException <tt>compositeType</tt> is null, or <tt>itemNames[]</tt> or <tt>itemValues[]</tt> is null or empty,
- * or one of the elements in <tt>itemNames[]</tt> is a null or empty string,
- * or <tt>itemNames[]</tt> and <tt>itemValues[]</tt> are not of the same size.
- * <p>
- * @throws OpenDataException <tt>itemNames[]</tt> or <tt>itemValues[]</tt>'s size differs from
- * the number of items defined in <tt>compositeType</tt>,
- * or one of the elements in <tt>itemNames[]</tt> does not exist as an item name defined in <tt>compositeType</tt>,
- * or one of the elements in <tt>itemValues[]</tt> is not a valid value for the corresponding item
- * as defined in <tt>compositeType</tt>.
- * <p>
- */
- public CompositeDataSupport(CompositeType compositeType, String[] itemNames, Object[] itemValues)
- throws OpenDataException {
+ * @param items the mappings of all the item names to their values;
+ * <tt>items</tt> must contain all the item names defined in <tt>compositeType</tt>;
+ * must not be null.
+ *
+ * @throws IllegalArgumentException <tt>compositeType</tt> is null, or
+ * <tt>items</tt> is null, or one of the keys in <tt>items</tt> is a null
+ * or empty string.
+ * @throws OpenDataException <tt>items</tt>' size differs from the
+ * number of items defined in <tt>compositeType</tt>, or one of the
+ * keys in <tt>items</tt> does not exist as an item name defined in
+ * <tt>compositeType</tt>, or one of the values in <tt>items</tt>
+ * is not a valid value for the corresponding item as defined in
+ * <tt>compositeType</tt>.
+ * @throws ArrayStoreException one or more keys in <tt>items</tt> is not of
+ * the class <tt>java.lang.String</tt>.
+ *
+ * @see #toMap
+ */
+ public CompositeDataSupport(CompositeType compositeType,
+ Map<Str