# HG changeset patch # User wetmore # Date 1205303822 25200 # Node ID 842a7d6767741154fd850111d10075a0c24e1f60 # Parent 6266821dc6521b6d6942eac1929c691cffbccced# Parent 3232f4bb7f1f5e9a88e558c748a6b31871277b93 Merge diff -r 6266821dc652 -r 842a7d676774 jdk/make/java/java/mapfile-vers --- a/jdk/make/java/java/mapfile-vers Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/make/java/java/mapfile-vers Tue Mar 11 23:37:02 2008 -0700 @@ -85,7 +85,6 @@ Java_java_io_FileOutputStream_close0; Java_java_io_FileOutputStream_initIDs; Java_java_io_FileOutputStream_open; - Java_java_io_FileOutputStream_openAppend; Java_java_io_FileOutputStream_write; Java_java_io_FileOutputStream_writeBytes; Java_java_io_FileSystem_getFileSystem; diff -r 6266821dc652 -r 842a7d676774 jdk/make/java/jli/Makefile --- a/jdk/make/java/jli/Makefile Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/make/java/jli/Makefile Tue Mar 11 23:37:02 2008 -0700 @@ -107,6 +107,7 @@ ifeq ($(PLATFORM), windows) EXTRA_LIBS = advapi32.lib \ + comctl32.lib \ user32.lib JAVALIB = diff -r 6266821dc652 -r 842a7d676774 jdk/make/java/main/java/Makefile --- a/jdk/make/java/main/java/Makefile Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/make/java/main/java/Makefile Tue Mar 11 23:37:02 2008 -0700 @@ -43,7 +43,7 @@ # Override the default version info with our own resource file (see 5106536) ifeq ($(PLATFORM), windows) -LDLIBS_COMMON += user32.lib +LDLIBS_COMMON += user32.lib comctl32.lib ifdef OPENJDK RC_FLAGS += -i "$(PLATFORM_SRC)/resource/icons" else diff -r 6266821dc652 -r 842a7d676774 jdk/make/java/main/javaw/Makefile --- a/jdk/make/java/main/javaw/Makefile Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/make/java/main/javaw/Makefile Tue Mar 11 23:37:02 2008 -0700 @@ -46,7 +46,7 @@ include $(BUILDDIR)/common/Defs.gmk OTHER_CPPFLAGS += -DJAVAW -LDLIBS_COMMON += user32.lib +LDLIBS_COMMON += user32.lib comctl32.lib # Override the default version info with our own resource file (see 5106536) ifeq ($(PLATFORM), windows) diff -r 6266821dc652 -r 842a7d676774 jdk/make/tools/src/build/tools/jdwpgen/CommandNode.java --- a/jdk/make/tools/src/build/tools/jdwpgen/CommandNode.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/make/tools/src/build/tools/jdwpgen/CommandNode.java Tue Mar 11 23:37:02 2008 -0700 @@ -32,9 +32,9 @@ void constrain(Context ctx) { if (components.size() == 3) { - Node out = (Node)components.get(0); - Node reply = (Node)components.get(1); - Node error = (Node)components.get(2); + Node out = components.get(0); + Node reply = components.get(1); + Node error = components.get(2); if (!(out instanceof OutNode)) { error("Expected 'Out' item, got: " + out); } @@ -45,7 +45,7 @@ error("Expected 'ErrorSet' item, got: " + error); } } else if (components.size() == 1) { - Node evt = (Node)components.get(0); + Node evt = components.get(0); if (!(evt instanceof EventNode)) { error("Expected 'Event' item, got: " + evt); } diff -r 6266821dc652 -r 842a7d676774 jdk/make/tools/src/build/tools/jdwpgen/ConstantSetNode.java --- a/jdk/make/tools/src/build/tools/jdwpgen/ConstantSetNode.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/make/tools/src/build/tools/jdwpgen/ConstantSetNode.java Tue Mar 11 23:37:02 2008 -0700 @@ -98,7 +98,7 @@ if (constantMap == null) { return ""; } - String com = (String) constantMap.get(key); + String com = constantMap.get(key); if(com == null){ return ""; } else { diff -r 6266821dc652 -r 842a7d676774 jdk/make/tools/src/build/tools/jdwpgen/RepeatNode.java --- a/jdk/make/tools/src/build/tools/jdwpgen/RepeatNode.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/make/tools/src/build/tools/jdwpgen/RepeatNode.java Tue Mar 11 23:37:02 2008 -0700 @@ -37,7 +37,7 @@ if (components.size() != 1) { error("Repeat must have exactly one member, use Group for more"); } - member = (Node)(components.get(0)); + member = components.get(0); if (!(member instanceof TypeNode)) { error("Repeat member must be type specifier"); } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/bin/java.c --- a/jdk/src/share/bin/java.c Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/bin/java.c Tue Mar 11 23:37:02 2008 -0700 @@ -205,9 +205,7 @@ _wc_enabled = cpwildcard; _ergo_policy = ergo; - if (javaw == JNI_TRUE) - SetJavaw(); - + InitLauncher(javaw); DumpState(); /* diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/bin/java.h --- a/jdk/src/share/bin/java.h Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/bin/java.h Tue Mar 11 23:37:02 2008 -0700 @@ -172,7 +172,6 @@ const char* GetFullVersion(); jboolean IsJavaArgs(); jboolean IsJavaw(); -void SetJavaw(); jint GetErgoPolicy(); jboolean ServerClassMachine(); @@ -180,5 +179,9 @@ static int ContinueInNewThread(InvocationFunctions* ifn, int argc, char** argv, char* jarfile, char* classname, int ret); +/* + * Initialize platform specific settings + */ +void InitLauncher(jboolean javaw); #endif /* _JAVA_H_ */ diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/bin/main.c --- a/jdk/src/share/bin/main.c Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/bin/main.c Tue Mar 11 23:37:02 2008 -0700 @@ -64,8 +64,6 @@ margv = argv; #endif /* JAVAW */ - JLI_SetTraceLauncher(); - return JLI_Launch(margc, margv, sizeof(const_jargs) / sizeof(char *), const_jargs, sizeof(const_appclasspath) / sizeof(char *), const_appclasspath, diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java --- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java Tue Mar 11 23:37:02 2008 -0700 @@ -43,6 +43,13 @@ import javax.management.NotCompliantMBeanException; import com.sun.jmx.mbeanserver.Util; +import com.sun.jmx.remote.util.EnvHelp; +import java.beans.BeanInfo; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Array; +import java.lang.reflect.InvocationTargetException; +import javax.management.AttributeNotFoundException; +import javax.management.openmbean.CompositeData; /** * This class contains the methods for performing all the tests needed to verify @@ -482,4 +489,33 @@ return null; } + + public static Object elementFromComplex(Object complex, String element) + throws AttributeNotFoundException { + try { + if (complex.getClass().isArray() && element.equals("length")) { + return Array.getLength(complex); + } else if (complex instanceof CompositeData) { + return ((CompositeData) complex).get(element); + } else { + // Java Beans introspection + // + BeanInfo bi = java.beans.Introspector.getBeanInfo(complex.getClass()); + PropertyDescriptor[] pds = bi.getPropertyDescriptors(); + for (PropertyDescriptor pd : pds) + if (pd.getName().equals(element)) + return pd.getReadMethod().invoke(complex); + throw new AttributeNotFoundException( + "Could not find the getter method for the property " + + element + " using the Java Beans introspector"); + } + } catch (InvocationTargetException e) { + throw new IllegalArgumentException(e); + } catch (AttributeNotFoundException e) { + throw e; + } catch (Exception e) { + throw EnvHelp.initCause( + new AttributeNotFoundException(e.getMessage()), e); + } + } } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/bdi/EventRequestSpec.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/bdi/EventRequestSpec.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/bdi/EventRequestSpec.java Tue Mar 11 23:37:02 2008 -0700 @@ -91,9 +91,7 @@ void attemptImmediateResolve(VirtualMachine vm) { // try to resolve immediately - Iterator iter = vm.allClasses().iterator(); - while (iter.hasNext()) { - ReferenceType refType = (ReferenceType)iter.next(); + for (ReferenceType refType : vm.allClasses()) { if (refSpec.matches(refType)) { try { resolve(refType); diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/bdi/EventRequestSpecList.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/bdi/EventRequestSpecList.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/bdi/EventRequestSpecList.java Tue Mar 11 23:37:02 2008 -0700 @@ -47,9 +47,8 @@ */ void resolve(ReferenceType refType) { synchronized(eventRequestSpecs) { - Iterator iter = eventRequestSpecs.iterator(); - while (iter.hasNext()) { - ((EventRequestSpec)iter.next()).attemptResolve(refType); + for (EventRequestSpec spec : eventRequestSpecs) { + spec.attemptResolve(refType); } } } @@ -79,7 +78,7 @@ BreakpointSpec createMethodBreakpoint(String classPattern, - String methodId, List methodArgs) { + String methodId, List methodArgs) { ReferenceTypeSpec refSpec = new PatternReferenceTypeSpec(classPattern); return new MethodBreakpointSpec(this, refSpec, @@ -132,47 +131,48 @@ // -------- notify routines -------------------- - private Vector specListeners() { - return (Vector)runtime.specListeners.clone(); + @SuppressWarnings("unchecked") + private Vector specListeners() { + return (Vector)runtime.specListeners.clone(); } void notifySet(EventRequestSpec spec) { - Vector l = specListeners(); + Vector l = specListeners(); SpecEvent evt = new SpecEvent(spec); for (int i = 0; i < l.size(); i++) { - spec.notifySet((SpecListener)l.elementAt(i), evt); + spec.notifySet(l.elementAt(i), evt); } } void notifyDeferred(EventRequestSpec spec) { - Vector l = specListeners(); + Vector l = specListeners(); SpecEvent evt = new SpecEvent(spec); for (int i = 0; i < l.size(); i++) { - spec.notifyDeferred((SpecListener)l.elementAt(i), evt); + spec.notifyDeferred(l.elementAt(i), evt); } } void notifyDeleted(EventRequestSpec spec) { - Vector l = specListeners(); + Vector l = specListeners(); SpecEvent evt = new SpecEvent(spec); for (int i = 0; i < l.size(); i++) { - spec.notifyDeleted((SpecListener)l.elementAt(i), evt); + spec.notifyDeleted(l.elementAt(i), evt); } } void notifyResolved(EventRequestSpec spec) { - Vector l = specListeners(); + Vector l = specListeners(); SpecEvent evt = new SpecEvent(spec); for (int i = 0; i < l.size(); i++) { - spec.notifyResolved((SpecListener)l.elementAt(i), evt); + spec.notifyResolved(l.elementAt(i), evt); } } void notifyError(EventRequestSpec spec, Exception exc) { - Vector l = specListeners(); + Vector l = specListeners(); SpecErrorEvent evt = new SpecErrorEvent(spec, exc); for (int i = 0; i < l.size(); i++) { - spec.notifyError((SpecListener)l.elementAt(i), evt); + spec.notifyError(l.elementAt(i), evt); } } } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/bdi/ExecutionManager.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/bdi/ExecutionManager.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/bdi/ExecutionManager.java Tue Mar 11 23:37:02 2008 -0700 @@ -232,10 +232,7 @@ if (pattern.startsWith("*.")) { // Wildcard matches any leading package name. pattern = pattern.substring(1); - List classes = vm().allClasses(); - Iterator iter = classes.iterator(); - while (iter.hasNext()) { - ReferenceType type = ((ReferenceType)iter.next()); + for (ReferenceType type : vm().allClasses()) { if (type.name().endsWith(pattern)) { result.add(type); } @@ -278,7 +275,7 @@ public ThreadGroupReference systemThreadGroup() throws NoSessionException { ensureActiveSession(); - return (ThreadGroupReference)vm().topLevelThreadGroups().get(0); + return vm().topLevelThreadGroups().get(0); } /* @@ -349,10 +346,9 @@ * attach sessions. */ VirtualMachineManager mgr = Bootstrap.virtualMachineManager(); - List connectors = mgr.attachingConnectors(); - AttachingConnector connector = (AttachingConnector)connectors.get(0); + AttachingConnector connector = mgr.attachingConnectors().get(0); Map arguments = connector.defaultArguments(); - ((Connector.Argument)arguments.get("port")).setValue(portName); + arguments.get("port").setValue(portName); Session newSession = internalAttach(connector, arguments); if (newSession != null) { @@ -504,10 +500,7 @@ * if so, it gets removed here. */ EventRequestManager mgr = vm().eventRequestManager(); - List requests = mgr.stepRequests(); - Iterator iter = requests.iterator(); - while (iter.hasNext()) { - StepRequest request = (StepRequest)iter.next(); + for (StepRequest request : mgr.stepRequests()) { if (request.thread().equals(thread)) { mgr.deleteEventRequest(request); break; @@ -591,7 +584,7 @@ if (session == null || thread == null) { return null; } - ThreadInfo info = (ThreadInfo)threadInfoMap.get(thread); + ThreadInfo info = threadInfoMap.get(thread); if (info == null) { //### Should not hardcode initial frame count and prefetch here! //info = new ThreadInfo(thread, 10, 10); @@ -607,24 +600,22 @@ void validateThreadInfo() { session.interrupted = true; - Iterator iter = threadInfoList.iterator(); - while (iter.hasNext()) { - ((ThreadInfo)iter.next()).validate(); + for (ThreadInfo threadInfo : threadInfoList) { + threadInfo.validate(); } } private void invalidateThreadInfo() { if (session != null) { session.interrupted = false; - Iterator iter = threadInfoList.iterator(); - while (iter.hasNext()) { - ((ThreadInfo)iter.next()).invalidate(); + for (ThreadInfo threadInfo : threadInfoList) { + threadInfo.invalidate(); } } } void removeThreadInfo(ThreadReference thread) { - ThreadInfo info = (ThreadInfo)threadInfoMap.get(thread); + ThreadInfo info = threadInfoMap.get(thread); if (info != null) { info.invalidate(); threadInfoMap.remove(thread); @@ -702,7 +693,7 @@ while (inputBuffer.size() < 1) { inputLock.wait(); } - line = (String)inputBuffer.removeLast(); + line = inputBuffer.removeLast(); } catch (InterruptedException e) {} } } @@ -774,7 +765,7 @@ public BreakpointSpec createMethodBreakpoint(String classPattern, - String methodId, List methodArgs) { + String methodId, List methodArgs) { return specList.createMethodBreakpoint(classPattern, methodId, methodArgs); } @@ -811,7 +802,7 @@ specList.install(spec, vm()); } - public List eventRequestSpecs() { + public List eventRequestSpecs() { return specList.eventRequestSpecs(); } } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/bdi/JDIEventSource.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/bdi/JDIEventSource.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/bdi/JDIEventSource.java Tue Mar 11 23:37:02 2008 -0700 @@ -82,9 +82,7 @@ boolean interrupted = es.suspendedAll(); es.notify(firstListener); boolean wantInterrupt = JDIEventSource.this.wantInterrupt; - for (Iterator it = session.runtime.jdiListeners.iterator(); - it.hasNext(); ) { - JDIListener jl = (JDIListener)it.next(); + for (JDIListener jl : session.runtime.jdiListeners) { es.notify(jl); } if (interrupted && !wantInterrupt) { diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/bdi/LineBreakpointSpec.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/bdi/LineBreakpointSpec.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/bdi/LineBreakpointSpec.java Tue Mar 11 23:37:02 2008 -0700 @@ -58,12 +58,12 @@ LineNotFoundException { Location location = null; try { - List locs = clazz.locationsOfLine(lineNumber()); + List locs = clazz.locationsOfLine(lineNumber()); if (locs.size() == 0) { throw new LineNotFoundException(); } // TODO handle multiple locations - location = (Location)locs.get(0); + location = locs.get(0); if (location.method() == null) { throw new LineNotFoundException(); } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/bdi/MethodBreakpointSpec.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/bdi/MethodBreakpointSpec.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/bdi/MethodBreakpointSpec.java Tue Mar 11 23:37:02 2008 -0700 @@ -34,11 +34,11 @@ public class MethodBreakpointSpec extends BreakpointSpec { String methodId; - List methodArgs; + List methodArgs; MethodBreakpointSpec(EventRequestSpecList specs, ReferenceTypeSpec refSpec, - String methodId, List methodArgs) { + String methodId, List methodArgs) { super(specs, refSpec); this.methodId = methodId; this.methodArgs = methodArgs; @@ -76,7 +76,7 @@ return methodId; } - public List methodArgs() { + public List methodArgs() { return methodArgs; } @@ -120,14 +120,13 @@ buffer.append('.'); buffer.append(methodId); if (methodArgs != null) { - Iterator iter = methodArgs.iterator(); boolean first = true; buffer.append('('); - while (iter.hasNext()) { + for (String name : methodArgs) { if (!first) { buffer.append(','); } - buffer.append((String)iter.next()); + buffer.append(name); first = false; } buffer.append(")"); @@ -151,8 +150,8 @@ * and if the number of arguments in the method matches the * number of names passed */ - private boolean compareArgTypes(Method method, List nameList) { - List argTypeNames = method.argumentTypeNames(); + private boolean compareArgTypes(Method method, List nameList) { + List argTypeNames = method.argumentTypeNames(); // If argument counts differ, we can stop here if (argTypeNames.size() != nameList.size()) { @@ -162,8 +161,8 @@ // Compare each argument type's name int nTypes = argTypeNames.size(); for (int i = 0; i < nTypes; ++i) { - String comp1 = (String)argTypeNames.get(i); - String comp2 = (String)nameList.get(i); + String comp1 = argTypeNames.get(i); + String comp2 = nameList.get(i); if (! comp1.equals(comp2)) { /* * We have to handle varargs. EG, the @@ -288,22 +287,17 @@ List argTypeNames = null; if (methodArgs() != null) { argTypeNames = new ArrayList(methodArgs().size()); - Iterator iter = methodArgs().iterator(); - while (iter.hasNext()) { - String name = (String)iter.next(); + for (String name : methodArgs()) { name = normalizeArgTypeName(name); argTypeNames.add(name); } } // Check each method in the class for matches - Iterator iter = clazz.methods().iterator(); Method firstMatch = null; // first method with matching name Method exactMatch = null; // (only) method with same name & sig int matchCount = 0; // > 1 implies overload - while (iter.hasNext()) { - Method candidate = (Method)iter.next(); - + for (Method candidate : clazz.methods()) { if (candidate.name().equals(methodName())) { matchCount++; diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/bdi/ThreadGroupIterator.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/bdi/ThreadGroupIterator.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/bdi/ThreadGroupIterator.java Tue Mar 11 23:37:02 2008 -0700 @@ -36,7 +36,7 @@ * Descend the tree of thread groups. * @author Robert G. Field */ -public class ThreadGroupIterator implements Iterator { +public class ThreadGroupIterator implements Iterator { private final Stack> stack = new Stack>(); @@ -56,8 +56,8 @@ } */ - private Iterator top() { - return (Iterator)stack.peek(); + private Iterator top() { + return stack.peek(); } /** @@ -77,12 +77,12 @@ return !stack.isEmpty(); } - public Object next() { + public ThreadGroupReference next() { return nextThreadGroup(); } public ThreadGroupReference nextThreadGroup() { - ThreadGroupReference tg = (ThreadGroupReference)top().next(); + ThreadGroupReference tg = top().next(); push(tg.threadGroups()); return tg; } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/bdi/ThreadIterator.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/bdi/ThreadIterator.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/bdi/ThreadIterator.java Tue Mar 11 23:37:02 2008 -0700 @@ -30,8 +30,8 @@ import java.util.List; import java.util.Iterator; -public class ThreadIterator implements Iterator { - Iterator it = null; +public class ThreadIterator implements Iterator { + Iterator it = null; ThreadGroupIterator tgi; public ThreadIterator(ThreadGroupReference tg) { @@ -53,12 +53,12 @@ return true; } - public Object next() { + public ThreadReference next() { return it.next(); } public ThreadReference nextThread() { - return (ThreadReference)next(); + return next(); } public void remove() { diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/expr/LValue.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/expr/LValue.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/expr/LValue.java Tue Mar 11 23:37:02 2008 -0700 @@ -191,11 +191,12 @@ return field; } - static List methodsByName(ReferenceType refType, String name, int kind) { - List list = refType.methodsByName(name); - Iterator iter = list.iterator(); + static List methodsByName(ReferenceType refType, + String name, int kind) { + List list = refType.methodsByName(name); + Iterator iter = list.iterator(); while (iter.hasNext()) { - Method method = (Method)iter.next(); + Method method = iter.next(); boolean isStatic = method.isStatic(); if (((kind == STATIC) && !isStatic) || ((kind == INSTANCE) && isStatic)) { @@ -231,21 +232,21 @@ * argType is not assignable from the type of the argument value. * IE, one is an Apple and the other is an Orange. */ - static int argumentsMatch(List argTypes, List arguments) { + static int argumentsMatch(List argTypes, List arguments) { if (argTypes.size() != arguments.size()) { return DIFFERENT; } - Iterator typeIter = argTypes.iterator(); - Iterator valIter = arguments.iterator(); + Iterator typeIter = argTypes.iterator(); + Iterator valIter = arguments.iterator(); int result = SAME; // If any pair aren't the same, change the // result to ASSIGNABLE. If any pair aren't // assignable, return DIFFERENT while (typeIter.hasNext()) { - Type argType = (Type)typeIter.next(); - Value value = (Value)valIter.next(); + Type argType = typeIter.next(); + Value value = valIter.next(); if (value == null) { // Null values can be passed to any non-primitive argument if (primitiveTypeNames.contains(argType.name())) { @@ -333,7 +334,7 @@ if (fromType instanceof ArrayType) { return isArrayAssignableTo((ArrayType)fromType, toType); } - List interfaces; + List interfaces; if (fromType instanceof ClassType) { ClassType superclazz = ((ClassType)fromType).superclass(); if ((superclazz != null) && isAssignableTo(superclazz, toType)) { @@ -344,9 +345,7 @@ // fromType must be an InterfaceType interfaces = ((InterfaceType)fromType).superinterfaces(); } - Iterator iter = interfaces.iterator(); - while (iter.hasNext()) { - InterfaceType interfaze = (InterfaceType)iter.next(); + for (InterfaceType interfaze : interfaces) { if (isAssignableTo(interfaze, toType)) { return true; } @@ -354,7 +353,8 @@ return false; } - static Method resolveOverload(List overloads, List arguments) + static Method resolveOverload(List overloads, + List arguments) throws ParseException { // If there is only one method to call, we'll just choose @@ -362,7 +362,7 @@ // the invoke will return a better error message than we // could generate here. if (overloads.size() == 1) { - return (Method)overloads.get(0); + return overloads.get(0); } // Resolving overloads is beyond the scope of this exercise. @@ -374,12 +374,10 @@ // methods to call. And, since casts aren't implemented, // the user can't use them to pick a particular overload to call. // IE, the user is out of luck in this case. - Iterator iter = overloads.iterator(); Method retVal = null; int assignableCount = 0; - while (iter.hasNext()) { - Method mm = (Method)iter.next(); - List argTypes; + for (Method mm : overloads) { + List argTypes; try { argTypes = mm.argumentTypes(); } catch (ClassNotLoadedException ee) { @@ -443,7 +441,7 @@ final ObjectReference obj; final ThreadReference thread; final Field matchingField; - final List overloads; + final List overloads; Method matchingMethod = null; List methodArguments = null; @@ -510,7 +508,7 @@ final ReferenceType refType; final ThreadReference thread; final Field matchingField; - final List overloads; + final List overloads; Method matchingMethod = null; List methodArguments = null; @@ -765,7 +763,7 @@ static LValue makeNewObject(VirtualMachine vm, ExpressionParser.GetFrame frameGetter, String className, List arguments) throws ParseException { - List classes = vm.classesByName(className); + List classes = vm.classesByName(className); if (classes.size() == 0) { throw new ParseException("No class named: " + className); } @@ -774,7 +772,7 @@ throw new ParseException("More than one class named: " + className); } - ReferenceType refType = (ReferenceType)classes.get(0); + ReferenceType refType = classes.get(0); if (!(refType instanceof ClassType)) { @@ -784,9 +782,9 @@ ClassType classType = (ClassType)refType; List methods = new ArrayList(classType.methods()); // writable - Iterator iter = methods.iterator(); + Iterator iter = methods.iterator(); while (iter.hasNext()) { - Method method = (Method)iter.next(); + Method method = iter.next(); if (!method.isConstructor()) { iter.remove(); } @@ -858,13 +856,13 @@ } // check for class name while (izer.hasMoreTokens()) { - List classes = vm.classesByName(first); + List classes = vm.classesByName(first); if (classes.size() > 0) { if (classes.size() > 1) { throw new ParseException("More than one class named: " + first); } else { - ReferenceType refType = (ReferenceType)classes.get(0); + ReferenceType refType = classes.get(0); LValue lval = new LValueStaticMember(refType, izer.nextToken(), thread); return nFields(lval, izer, thread); diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/gui/ClassTreeTool.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/gui/ClassTreeTool.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/gui/ClassTreeTool.java Tue Mar 11 23:37:02 2008 -0700 @@ -124,9 +124,7 @@ public void sessionStart(EventObject e) { // Get system classes and any others loaded before attaching. try { - Iterator iter = runtime.allClasses().iterator(); - while (iter.hasNext()) { - ReferenceType type = ((ReferenceType)iter.next()); + for (ReferenceType type : runtime.allClasses()) { root.addClass(type); } } catch (VMDisconnectedException ee) { diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/gui/CommandInterpreter.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/gui/CommandInterpreter.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/gui/CommandInterpreter.java Tue Mar 11 23:37:02 2008 -0700 @@ -77,7 +77,7 @@ while (ti.hasNext()) { tlist.add(ti.nextThread()); } - threads = (ThreadReference[])tlist.toArray(new ThreadReference[tlist.size()]); + threads = tlist.toArray(new ThreadReference[tlist.size()]); } return threads; } @@ -146,11 +146,9 @@ // Command: classes private void commandClasses() throws NoSessionException { - List list = runtime.allClasses(); OutputSink out = env.getOutputSink(); //out.println("** classes list **"); - for (int i = 0 ; i < list.size() ; i++) { - ReferenceType refType = (ReferenceType)list.get(i); + for (ReferenceType refType : runtime.allClasses()) { out.println(refType.name()); } out.show(); @@ -167,16 +165,16 @@ String idClass = t.nextToken(); ReferenceType cls = findClass(idClass); if (cls != null) { - List methods = cls.allMethods(); + List methods = cls.allMethods(); OutputSink out = env.getOutputSink(); for (int i = 0; i < methods.size(); i++) { - Method method = (Method)methods.get(i); + Method method = methods.get(i); out.print(method.declaringType().name() + " " + method.name() + "("); - Iterator it = method.argumentTypeNames().iterator(); + Iterator it = method.argumentTypeNames().iterator(); if (it.hasNext()) { while (true) { - out.print((String)it.next()); + out.print(it.next()); if (!it.hasNext()) { break; } @@ -193,10 +191,10 @@ } private ReferenceType findClass(String pattern) throws NoSessionException { - List results = runtime.findClassesMatchingPattern(pattern); + List results = runtime.findClassesMatchingPattern(pattern); if (results.size() > 0) { //### Should handle multiple results sensibly. - return (ReferenceType)results.get(0); + return results.get(0); } return null; } @@ -235,11 +233,11 @@ private int printThreadGroup(OutputSink out, ThreadGroupReference tg, int iThread) { out.println("Group " + tg.name() + ":"); - List tlist = tg.threads(); + List tlist = tg.threads(); int maxId = 0; int maxName = 0; for (int i = 0 ; i < tlist.size() ; i++) { - ThreadReference thr = (ThreadReference)tlist.get(i); + ThreadReference thr = tlist.get(i); int len = Utils.description(thr).length(); if (len > maxId) maxId = len; @@ -254,7 +252,7 @@ String maxNumString = String.valueOf(iThread + tlist.size()); int maxNumDigits = maxNumString.length(); for (int i = 0 ; i < tlist.size() ; i++) { - ThreadReference thr = (ThreadReference)tlist.get(i); + ThreadReference thr = tlist.get(i); char buf[] = new char[80]; for (int j = 0; j < 79; j++) { buf[j] = ' '; @@ -283,9 +281,7 @@ sbOut.setLength(79); out.println(sbOut.toString()); } - List tglist = tg.threadGroups(); - for (int ig = 0; ig < tglist.size(); ig++) { - ThreadGroupReference tg0 = (ThreadGroupReference)tglist.get(ig); + for (ThreadGroupReference tg0 : tg.threadGroups()) { if (!tg.equals(tg0)) { // TODO ref mgt iThread += printThreadGroup(out, tg0, iThread + tlist.size()); } @@ -733,7 +729,7 @@ if (token.toLowerCase().equals("all")) { ThreadIterator it = allThreads(); while (it.hasNext()) { - ThreadReference thread = (ThreadReference)it.next(); + ThreadReference thread = it.next(); out.println(thread.name() + ": "); dumpStack(thread, showPC); } @@ -755,7 +751,7 @@ //env.failure("Target VM must be in interrupted state."); //env.failure("Current thread isn't suspended."); //### Should handle extremely long stack traces sensibly for user. - List stack = null; + List stack = null; try { stack = thread.frames(); } catch (IncompatibleThreadStateException e) { @@ -772,7 +768,7 @@ OutputSink out = env.getOutputSink(); int nFrames = stack.size(); for (int i = frameIndex; i < nFrames; i++) { - StackFrame frame = (StackFrame)stack.get(i); + StackFrame frame = stack.get(i); Location loc = frame.location(); Method meth = loc.method(); out.print(" [" + (i + 1) + "] "); @@ -780,7 +776,7 @@ out.print('.'); out.print(meth.name()); out.print(" ("); - if (meth instanceof Method && ((Method)meth).isNative()) { + if (meth.isNative()) { out.print("native method"); } else if (loc.lineNumber() != -1) { try { @@ -806,14 +802,13 @@ private void listEventRequests() throws NoSessionException { // Print set breakpoints - Iterator iter = runtime.eventRequestSpecs().iterator(); - if (!iter.hasNext()) { + List specs = runtime.eventRequestSpecs(); + if (specs.isEmpty()) { env.notice("No breakpoints/watchpoints/exceptions set."); } else { OutputSink out = env.getOutputSink(); out.println("Current breakpoints/watchpoints/exceptions set:"); - while (iter.hasNext()) { - EventRequestSpec bp = (EventRequestSpec)iter.next(); + for (EventRequestSpec bp : specs) { out.println("\t" + bp); } out.show(); @@ -926,13 +921,13 @@ //### need 'clear all' BreakpointSpec bpSpec = parseBreakpointSpec(t.nextToken()); if (bpSpec != null) { - Iterator iter = runtime.eventRequestSpecs().iterator(); - if (!iter.hasNext()) { + List specs = runtime.eventRequestSpecs(); + + if (specs.isEmpty()) { env.notice("No breakpoints set."); } else { - List toDelete = new ArrayList(); - while (iter.hasNext()) { - BreakpointSpec spec = (BreakpointSpec)iter.next(); + List toDelete = new ArrayList(); + for (EventRequestSpec spec : specs) { if (spec.equals(bpSpec)) { toDelete.add(spec); } @@ -941,7 +936,7 @@ if (toDelete.size() <= 1) { env.notice("No matching breakpoint set."); } - for (BreakpointSpec spec : toDelete) { + for (EventRequestSpec spec : toDelete) { runtime.delete(spec); } } @@ -988,7 +983,7 @@ lineno = Integer.valueOf(id).intValue(); } catch (NumberFormatException nfe) { // It isn't -- see if it's a method name. - List meths = refType.methodsByName(id); + List meths = refType.methodsByName(id); if (meths == null || meths.size() == 0) { env.failure(id + " is not a valid line number or " + @@ -1001,7 +996,7 @@ refType.name()); return; } - loc = ((Method)meths.get(0)).location(); + loc = meths.get(0).location(); lineno = loc.lineNumber(); } } @@ -1121,7 +1116,7 @@ return; } - List vars; + List vars; try { vars = frame.visibleVariables(); if (vars == null || vars.size() == 0) { @@ -1136,15 +1131,13 @@ OutputSink out = env.getOutputSink(); out.println("Method arguments:"); - for (Iterator it = vars.iterator(); it.hasNext(); ) { - LocalVariable var = (LocalVariable)it.next(); + for (LocalVariable var : vars) { if (var.isArgument()) { printVar(out, var, frame); } } out.println("Local variables:"); - for (Iterator it = vars.iterator(); it.hasNext(); ) { - LocalVariable var = (LocalVariable)it.next(); + for (LocalVariable var : vars) { if (!var.isArgument()) { printVar(out, var, frame); } @@ -1245,8 +1238,7 @@ private void dump(OutputSink out, ObjectReference obj, ReferenceType refType, ReferenceType refTypeBase) { - for (Iterator it = refType.fields().iterator(); it.hasNext(); ) { - Field field = (Field)it.next(); + for (Field field : refType.fields()) { out.print(" "); if (!refType.equals(refTypeBase)) { out.print(refType.name() + "."); @@ -1261,9 +1253,8 @@ dump(out, obj, sup, refTypeBase); } } else if (refType instanceof InterfaceType) { - List sups = ((InterfaceType)refType).superinterfaces(); - for (Iterator it = sups.iterator(); it.hasNext(); ) { - dump(out, obj, (ReferenceType)it.next(), refTypeBase); + for (InterfaceType sup : ((InterfaceType)refType).superinterfaces()) { + dump(out, obj, sup, refTypeBase); } } } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/gui/JDBFileFilter.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/gui/JDBFileFilter.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/gui/JDBFileFilter.java Tue Mar 11 23:37:02 2008 -0700 @@ -201,11 +201,11 @@ if(description == null || isExtensionListInDescription()) { fullDescription = description==null ? "(" : description + " ("; // build the description from the extension list - Enumeration extensions = filters.keys(); + Enumeration extensions = filters.keys(); if(extensions != null) { - fullDescription += "." + (String) extensions.nextElement(); + fullDescription += "." + extensions.nextElement(); while (extensions.hasMoreElements()) { - fullDescription += ", " + (String) extensions.nextElement(); + fullDescription += ", " + extensions.nextElement(); } } fullDescription += ")"; diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/gui/LaunchTool.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/gui/LaunchTool.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/gui/LaunchTool.java Tue Mar 11 23:37:02 2008 -0700 @@ -131,14 +131,13 @@ final JPanel radioPanel = new JPanel(); final ButtonGroup radioGroup = new ButtonGroup(); VirtualMachineManager manager = Bootstrap.virtualMachineManager(); - List all = manager.allConnectors(); + List all = manager.allConnectors(); Map modelToConnector = new HashMap(all.size(), 0.5f); dialog.setModal(true); dialog.setTitle("Select Connector Type"); radioPanel.setLayout(new BoxLayout(radioPanel, BoxLayout.Y_AXIS)); - for (Iterator it = all.iterator(); it.hasNext(); ) { - Connector connector = (Connector)it.next(); + for (Connector connector : all) { JRadioButton radio = new JRadioButton(connector.description()); modelToConnector.put(radio.getModel(), connector); radioPanel.add(radio); @@ -166,7 +165,7 @@ dialog.show(); return oked[0] ? - (Connector)(modelToConnector.get(radioGroup.getSelection())) : + modelToConnector.get(radioGroup.getSelection()) : null; } @@ -188,13 +187,12 @@ // guts.add(new JLabel(connector.description())); final List argReps = new ArrayList(args.size()); - for (Iterator it = args.values().iterator(); it.hasNext(); ) { - Object arg = it.next(); + for (Connector.Argument arg : args.values()) { ArgRep ar; if (arg instanceof Connector.BooleanArgument) { ar = new BooleanArgRep((Connector.BooleanArgument)arg, guts); } else { - ar = new StringArgRep((Connector.Argument)arg, guts); + ar = new StringArgRep(arg, guts); } argReps.add(ar); } @@ -202,8 +200,7 @@ JPanel buttonPanel = okCancel( dialog, new ActionListener() { public void actionPerformed(ActionEvent event) { - for (Iterator it = argReps.iterator(); it.hasNext(); ) { - ArgRep ar = (ArgRep)it.next(); + for (ArgRep ar : argReps) { if (!ar.isSpecified()) { JOptionPane.showMessageDialog(dialog, ar.arg.label() + diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/gui/SearchPath.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/gui/SearchPath.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/gui/SearchPath.java Tue Mar 11 23:37:02 2008 -0700 @@ -42,7 +42,7 @@ dlist.add(st.nextToken()); } pathString = searchPath; - pathArray = (String[])dlist.toArray(new String[dlist.size()]); + pathArray = dlist.toArray(new String[dlist.size()]); } public boolean isEmpty() { @@ -54,7 +54,7 @@ } public String[] asArray() { - return (String[])pathArray.clone(); + return pathArray.clone(); } public File resolve(String relativeFileName) { @@ -89,7 +89,7 @@ } } } - return (String[])s.toArray(new String[s.size()]); + return s.toArray(new String[s.size()]); } } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/gui/SourceManager.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/gui/SourceManager.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/gui/SourceManager.java Tue Mar 11 23:37:02 2008 -0700 @@ -113,7 +113,7 @@ * Returns null if not available. */ public SourceModel sourceForClass(ReferenceType refType) { - SourceModel sm = (SourceModel)classToSource.get(refType); + SourceModel sm = classToSource.get(refType); if (sm != null) { return sm; } @@ -140,10 +140,10 @@ */ //### Use hash table for this? public SourceModel sourceForFile(File path) { - Iterator iter = sourceList.iterator(); + Iterator iter = sourceList.iterator(); SourceModel sm = null; while (iter.hasNext()) { - SourceModel candidate = (SourceModel)iter.next(); + SourceModel candidate = iter.next(); if (candidate.fileName().equals(path)) { sm = candidate; iter.remove(); // Will move to start of list. diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/gui/SourceModel.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/gui/SourceModel.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/gui/SourceModel.java Tue Mar 11 23:37:02 2008 -0700 @@ -187,22 +187,17 @@ * when sourceLines is set. */ private void markClassLines(ReferenceType refType) { - List methods = refType.methods(); - for (Iterator mit = methods.iterator(); mit.hasNext();) { - Method meth = (Method)mit.next(); + for (Method meth : refType.methods()) { try { - List lines = meth.allLineLocations(); - for (Iterator lit = lines.iterator(); lit.hasNext();) { - Location loc = (Location)lit.next(); + for (Location loc : meth.allLineLocations()) { showExecutable(loc.lineNumber(), refType); } } catch (AbsentInformationException exc) { // do nothing } } - List bps = env.getExecutionManager().eventRequestManager().breakpointRequests(); - for (Iterator it = bps.iterator(); it.hasNext();) { - BreakpointRequest bp = (BreakpointRequest)it.next(); + for (BreakpointRequest bp : + env.getExecutionManager().eventRequestManager().breakpointRequests()) { if (bp.location() != null) { Location loc = bp.location(); if (loc.declaringType().equals(refType)) { @@ -224,8 +219,8 @@ } finally { reader.close(); } - for (Iterator it = classes.iterator(); it.hasNext();) { - markClassLines((ClassType)it.next()); + for (ReferenceType refType : classes) { + markClassLines(refType); } } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/gui/StackTraceTool.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/gui/StackTraceTool.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/gui/StackTraceTool.java Tue Mar 11 23:37:02 2008 -0700 @@ -139,7 +139,7 @@ String methName = meth.declaringType().name() + '.' + meth.name(); String position = ""; - if (meth instanceof Method && ((Method)meth).isNative()) { + if (meth.isNative()) { position = " (native method)"; } else if (loc.lineNumber() != -1) { position = ":" + loc.lineNumber(); diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/gui/ThreadTreeTool.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/gui/ThreadTreeTool.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/gui/ThreadTreeTool.java Tue Mar 11 23:37:02 2008 -0700 @@ -133,9 +133,7 @@ public void sessionStart(EventObject e) { try { - Iterator iter = runtime.allThreads().iterator(); - while (iter.hasNext()) { - ThreadReference thread = ((ThreadReference)iter.next()); + for (ThreadReference thread : runtime.allThreads()) { root.addThread(thread); } } catch (VMDisconnectedException ee) { @@ -244,16 +242,16 @@ } } - private void addThread(List threadPath, ThreadReference thread) { + private void addThread(List threadPath, ThreadReference thread) { int size = threadPath.size(); if (size == 0) { return; } else if (size == 1) { - String name = (String)threadPath.get(0); + String name = threadPath.get(0); insertNode(name, thread); } else { - String head = (String)threadPath.get(0); - List tail = threadPath.subList(1, size); + String head = threadPath.get(0); + List tail = threadPath.subList(1, size); ThreadTreeNode child = insertNode(head, null); child.addThread(tail, thread); } @@ -288,17 +286,17 @@ } } - private void removeThread(List threadPath, ThreadReference thread) { + private void removeThread(List threadPath, ThreadReference thread) { int size = threadPath.size(); if (size == 0) { return; } else if (size == 1) { - String name = (String)threadPath.get(0); + String name = threadPath.get(0); ThreadTreeNode child = findLeafNode(thread, name); treeModel.removeNodeFromParent(child); } else { - String head = (String)threadPath.get(0); - List tail = threadPath.subList(1, size); + String head = threadPath.get(0); + List tail = threadPath.subList(1, size); ThreadTreeNode child = findInternalNode(head); child.removeThread(tail, thread); if (child.isThreadGroup() && child.getChildCount() < 1) { diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/tty/BreakpointSpec.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/tty/BreakpointSpec.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/tty/BreakpointSpec.java Tue Mar 11 23:37:02 2008 -0700 @@ -34,7 +34,7 @@ class BreakpointSpec extends EventRequestSpec { String methodId; - List methodArgs; + List methodArgs; int lineNumber; BreakpointSpec(ReferenceTypeSpec refSpec, int lineNumber) { @@ -45,7 +45,7 @@ } BreakpointSpec(ReferenceTypeSpec refSpec, String methodId, - List methodArgs) throws MalformedMemberNameException { + List methodArgs) throws MalformedMemberNameException { super(refSpec); this.methodId = methodId; this.methodArgs = methodArgs; @@ -83,7 +83,7 @@ return lineNumber; } - List methodArgs() { + List methodArgs() { return methodArgs; } @@ -146,14 +146,13 @@ buffer.append('.'); buffer.append(methodId); if (methodArgs != null) { - Iterator iter = methodArgs.iterator(); boolean first = true; buffer.append('('); - while (iter.hasNext()) { + for (String arg : methodArgs) { if (!first) { buffer.append(','); } - buffer.append((String)iter.next()); + buffer.append(arg); first = false; } buffer.append(")"); @@ -176,12 +175,12 @@ location = method.location(); } else { // let AbsentInformationException be thrown - List locs = refType.locationsOfLine(lineNumber()); + List locs = refType.locationsOfLine(lineNumber()); if (locs.size() == 0) { throw new LineNotFoundException(); } // TO DO: handle multiple locations - location = (Location)locs.get(0); + location = locs.get(0); if (location.method() == null) { throw new LineNotFoundException(); } @@ -202,8 +201,8 @@ * and if the number of arguments in the method matches the * number of names passed */ - private boolean compareArgTypes(Method method, List nameList) { - List argTypeNames = method.argumentTypeNames(); + private boolean compareArgTypes(Method method, List nameList) { + List argTypeNames = method.argumentTypeNames(); // If argument counts differ, we can stop here if (argTypeNames.size() != nameList.size()) { @@ -213,8 +212,8 @@ // Compare each argument type's name int nTypes = argTypeNames.size(); for (int i = 0; i < nTypes; ++i) { - String comp1 = (String)argTypeNames.get(i); - String comp2 = (String)nameList.get(i); + String comp1 = argTypeNames.get(i); + String comp2 = nameList.get(i); if (! comp1.equals(comp2)) { /* * We have to handle varargs. EG, the @@ -331,22 +330,17 @@ List argTypeNames = null; if (methodArgs() != null) { argTypeNames = new ArrayList(methodArgs().size()); - Iterator iter = methodArgs().iterator(); - while (iter.hasNext()) { - String name = (String)iter.next(); + for (String name : methodArgs()) { name = normalizeArgTypeName(name); argTypeNames.add(name); } } // Check each method in the class for matches - Iterator iter = refType.methods().iterator(); Method firstMatch = null; // first method with matching name Method exactMatch = null; // (only) method with same name & sig int matchCount = 0; // > 1 implies overload - while (iter.hasNext()) { - Method candidate = (Method)iter.next(); - + for (Method candidate : refType.methods()) { if (candidate.name().equals(methodName())) { matchCount++; diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/tty/Commands.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/tty/Commands.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/tty/Commands.java Tue Mar 11 23:37:02 2008 -0700 @@ -157,16 +157,16 @@ buf.append(method.name()); buf.append("("); - List args = method.argumentTypeNames(); + List args = method.argumentTypeNames(); int lastParam = args.size() - 1; // output param types except for the last for (int ii = 0; ii < lastParam; ii++) { - buf.append((String)args.get(ii)); + buf.append(args.get(ii)); buf.append(", "); } if (lastParam >= 0) { // output the last param - String lastStr = (String)args.get(lastParam); + String lastStr = args.get(lastParam); if (method.isVarArgs()) { // lastParam is an array. Replace the [] with ... buf.append(lastStr.substring(0, lastStr.length() - 2)); @@ -180,12 +180,11 @@ } void commandConnectors(VirtualMachineManager vmm) { - Iterator iter = vmm.allConnectors().iterator(); - if (iter.hasNext()) { + Collection ccs = vmm.allConnectors(); + if (ccs.isEmpty()) { MessageOutput.println("Connectors available"); } - while (iter.hasNext()) { - Connector cc = (Connector)iter.next(); + for (Connector cc : ccs) { String transportName = cc.transport() == null ? "null" : cc.transport().name(); MessageOutput.println(); @@ -193,10 +192,7 @@ new Object [] {cc.name(), transportName}); MessageOutput.println("Connector description", cc.description()); - Iterator argIter = cc.defaultArguments().values().iterator(); - if (argIter.hasNext()) { - while (argIter.hasNext()) { - Connector.Argument aa = (Connector.Argument)argIter.next(); + for (Connector.Argument aa : cc.defaultArguments().values()) { MessageOutput.println(); boolean requiredArgument = aa.mustSpecify(); @@ -215,16 +211,12 @@ } } - } } void commandClasses() { - List list = Env.vm().allClasses(); - StringBuffer classList = new StringBuffer(); - for (int i = 0 ; i < list.size() ; i++) { - ReferenceType refType = (ReferenceType)list.get(i); + for (ReferenceType refType : Env.vm().allClasses()) { classList.append(refType.name()); classList.append("\n"); } @@ -232,7 +224,7 @@ } void commandClass(StringTokenizer t) { - List list = Env.vm().allClasses(); + List list = Env.vm().allClasses(); if (!t.hasMoreTokens()) { MessageOutput.println("No class specified."); @@ -265,51 +257,31 @@ superclass = showAll ? superclass.superclass() : null; } - List interfaces = showAll ? clazz.allInterfaces() - : clazz.interfaces(); - Iterator iter = interfaces.iterator(); - while (iter.hasNext()) { - InterfaceType interfaze = (InterfaceType)iter.next(); + List interfaces = + showAll ? clazz.allInterfaces() : clazz.interfaces(); + for (InterfaceType interfaze : interfaces) { MessageOutput.println("implements:", interfaze.name()); } - List subs = clazz.subclasses(); - iter = subs.iterator(); - while (iter.hasNext()) { - ClassType sub = (ClassType)iter.next(); + for (ClassType sub : clazz.subclasses()) { MessageOutput.println("subclass:", sub.name()); } - List nested = clazz.nestedTypes(); - iter = nested.iterator(); - while (iter.hasNext()) { - ReferenceType nest = (ReferenceType)iter.next(); + for (ReferenceType nest : clazz.nestedTypes()) { MessageOutput.println("nested:", nest.name()); } } else if (type instanceof InterfaceType) { InterfaceType interfaze = (InterfaceType)type; MessageOutput.println("Interface:", interfaze.name()); - List supers = interfaze.superinterfaces(); - Iterator iter = supers.iterator(); - while (iter.hasNext()) { - InterfaceType superinterface = (InterfaceType)iter.next(); + for (InterfaceType superinterface : interfaze.superinterfaces()) { MessageOutput.println("extends:", superinterface.name()); } - List subs = interfaze.subinterfaces(); - iter = subs.iterator(); - while (iter.hasNext()) { - InterfaceType sub = (InterfaceType)iter.next(); + for (InterfaceType sub : interfaze.subinterfaces()) { MessageOutput.println("subinterface:", sub.name()); } - List implementors = interfaze.implementors(); - iter = implementors.iterator(); - while (iter.hasNext()) { - ClassType implementor = (ClassType)iter.next(); + for (ClassType implementor : interfaze.implementors()) { MessageOutput.println("implementor:", implementor.name()); } - List nested = interfaze.nestedTypes(); - iter = nested.iterator(); - while (iter.hasNext()) { - ReferenceType nest = (ReferenceType)iter.next(); + for (ReferenceType nest : interfaze.nestedTypes()) { MessageOutput.println("nested:", nest.name()); } } else { // array type @@ -327,10 +299,8 @@ String idClass = t.nextToken(); ReferenceType cls = Env.getReferenceTypeFromToken(idClass); if (cls != null) { - List methods = cls.allMethods(); StringBuffer methodsList = new StringBuffer(); - for (int i = 0; i < methods.size(); i++) { - Method method = (Method)methods.get(i); + for (Method method : cls.allMethods()) { methodsList.append(method.declaringType().name()); methodsList.append(" "); methodsList.append(typedName(method)); @@ -351,11 +321,10 @@ String idClass = t.nextToken(); ReferenceType cls = Env.getReferenceTypeFromToken(idClass); if (cls != null) { - List fields = cls.allFields(); - List visible = cls.visibleFields(); + List fields = cls.allFields(); + List visible = cls.visibleFields(); StringBuffer fieldsList = new StringBuffer(); - for (int i = 0; i < fields.size(); i++) { - Field field = (Field)fields.get(i); + for (Field field : fields) { String s; if (!visible.contains(field)) { s = MessageOutput.format("list field typename and name hidden", @@ -386,7 +355,7 @@ int maxIdLength = 0; int maxNameLength = 0; while (threadIter.hasNext()) { - ThreadReference thr = (ThreadReference)threadIter.next(); + ThreadReference thr = threadIter.next(); maxIdLength = Math.max(maxIdLength, Env.description(thr).length()); maxNameLength = Math.max(maxNameLength, @@ -395,7 +364,7 @@ threadIter = new ThreadIterator(tg); while (threadIter.hasNext()) { - ThreadReference thr = (ThreadReference)threadIter.next(); + ThreadReference thr = threadIter.next(); if (thr.threadGroup() == null) { continue; } @@ -588,9 +557,7 @@ private List allThreads(ThreadGroupReference group) { List list = new ArrayList(); list.addAll(group.threads()); - Iterator iter = group.threadGroups().iterator(); - while (iter.hasNext()) { - ThreadGroupReference child = (ThreadGroupReference)iter.next(); + for (ThreadGroupReference child : group.threadGroups()) { list.addAll(allThreads(child)); } return list; @@ -641,10 +608,7 @@ * if so, it gets removed here. */ EventRequestManager mgr = Env.vm().eventRequestManager(); - List requests = mgr.stepRequests(); - Iterator iter = requests.iterator(); - while (iter.hasNext()) { - StepRequest request = (StepRequest)iter.next(); + for (StepRequest request : mgr.stepRequests()) { if (request.thread().equals(thread)) { mgr.deleteEventRequest(request); break; @@ -768,9 +732,7 @@ boolean noExceptions = true; // Print a listing of the catch patterns currently in place - Iterator iter = Env.specList.eventRequestSpecs().iterator(); - while (iter.hasNext()) { - EventRequestSpec spec = (EventRequestSpec)iter.next(); + for (EventRequestSpec spec : Env.specList.eventRequestSpecs()) { if (spec instanceof ExceptionSpec) { if (noExceptions) { noExceptions = false; @@ -928,7 +890,7 @@ } private void dumpStack(ThreadInfo threadInfo, boolean showPC) { - List stack = null; + List stack = null; try { stack = threadInfo.getStack(); } catch (IncompatibleThreadStateException e) { @@ -940,7 +902,7 @@ } else { int nFrames = stack.size(); for (int i = threadInfo.getCurrentFrameIndex(); i < nFrames; i++) { - StackFrame frame = (StackFrame)stack.get(i); + StackFrame frame = stack.get(i); dumpFrame (i, showPC, frame); } } @@ -956,7 +918,7 @@ long lineNumber = loc.lineNumber(); String methodInfo = null; - if (meth instanceof Method && ((Method)meth).isNative()) { + if (meth.isNative()) { methodInfo = MessageOutput.format("native method"); } else if (lineNumber != -1) { try { @@ -994,9 +956,7 @@ } else { String token = t.nextToken(); if (token.toLowerCase().equals("all")) { - Iterator iter = ThreadInfo.threads().iterator(); - while (iter.hasNext()) { - ThreadInfo threadInfo = (ThreadInfo)iter.next(); + for (ThreadInfo threadInfo : ThreadInfo.threads()) { MessageOutput.println("Thread:", threadInfo.getThread().name()); dumpStack(threadInfo, showPC); @@ -1051,9 +1011,7 @@ boolean noBreakpoints = true; // Print set breakpoints - Iterator iter = Env.specList.eventRequestSpecs().iterator(); - while (iter.hasNext()) { - EventRequestSpec spec = (EventRequestSpec)iter.next(); + for (EventRequestSpec spec : Env.specList.eventRequestSpecs()) { if (spec instanceof BreakpointSpec) { if (noBreakpoints) { noBreakpoints = false; @@ -1075,7 +1033,7 @@ protected BreakpointSpec parseBreakpointSpec(StringTokenizer t, String atForm, String inForm) { - EventRequestSpec breakpoint = null; + BreakpointSpec breakpoint = null; try { String token = t.nextToken(":( \t\n\r"); @@ -1149,7 +1107,7 @@ printBreakpointCommandUsage(atForm, inForm); return null; } - return (BreakpointSpec)breakpoint; + return breakpoint; } private void resolveNow(EventRequestSpec spec) { @@ -1209,8 +1167,8 @@ } } - private List parseWatchpointSpec(StringTokenizer t) { - List list = new ArrayList(); + private List parseWatchpointSpec(StringTokenizer t) { + List list = new ArrayList(); boolean access = false; boolean modification = false; int suspendPolicy = EventRequest.SUSPEND_ALL; @@ -1242,7 +1200,7 @@ fieldName = fieldName.substring(dot+1); try { - EventRequestSpec spec; + WatchpointSpec spec; if (access) { spec = Env.specList.createAccessWatchpoint(className, fieldName); @@ -1269,9 +1227,8 @@ return; } - Iterator iter = parseWatchpointSpec(t).iterator(); - while (iter.hasNext()) { - resolveNow((WatchpointSpec)iter.next()); + for (WatchpointSpec spec : parseWatchpointSpec(t)) { + resolveNow(spec); } } @@ -1281,9 +1238,7 @@ return; } - Iterator iter = parseWatchpointSpec(t).iterator(); - while (iter.hasNext()) { - WatchpointSpec spec = (WatchpointSpec)iter.next(); + for (WatchpointSpec spec : parseWatchpointSpec(t)) { if (Env.specList.delete(spec)) { MessageOutput.println("Removed:", spec.toString()); } else { @@ -1482,7 +1437,7 @@ lineno = n.intValue(); } catch (java.text.ParseException jtpe) { // It isn't -- see if it's a method name. - List meths = refType.methodsByName(id); + List meths = refType.methodsByName(id); if (meths == null || meths.size() == 0) { MessageOutput.println("is not a valid line number or method name for", new Object [] {id, refType.name()}); @@ -1492,7 +1447,7 @@ new Object [] {id, refType.name()}); return; } - loc = ((Method)meths.get(0)).location(); + loc = meths.get(0).location(); lineno = loc.lineNumber(); } } @@ -1539,14 +1494,11 @@ try { ReferenceType refType = Env.getReferenceTypeFromToken(idClass); if (refType != null) { - List lines = null; + List lines = null; if (idMethod == null) { lines = refType.allLineLocations(); } else { - List methods = refType.allMethods(); - Iterator iter = methods.iterator(); - while (iter.hasNext()) { - Method method = (Method)iter.next(); + for (Method method : refType.allMethods()) { if (method.name().equals(idMethod)) { lines = method.allLineLocations(); } @@ -1555,9 +1507,7 @@ MessageOutput.println("is not a valid method name", idMethod); } } - Iterator iter = lines.iterator(); - while (iter.hasNext()) { - Location line = (Location)iter.next(); + for (Location line : lines) { MessageOutput.printDirectln(line.toString());// Special case: use printDirectln() } } else { @@ -1620,21 +1570,19 @@ MessageOutput.println("No local variables"); return; } - Map values = frame.getValues(vars); + Map values = frame.getValues(vars); MessageOutput.println("Method arguments:"); - for (Iterator it = vars.iterator(); it.hasNext(); ) { - LocalVariable var = (LocalVariable)it.next(); + for (LocalVariable var : vars) { if (var.isArgument()) { - Value val = (Value)values.get(var); + Value val = values.get(var); printVar(var, val); } } MessageOutput.println("Local variables:"); - for (Iterator it = vars.iterator(); it.hasNext(); ) { - LocalVariable var = (LocalVariable)it.next(); + for (LocalVariable var : vars) { if (!var.isArgument()) { - Value val = (Value)values.get(var); + Value val = values.get(var); printVar(var, val); } } @@ -1647,9 +1595,8 @@ private void dump(ObjectReference obj, ReferenceType refType, ReferenceType refTypeBase) { - for (Iterator it = refType.fields().iterator(); it.hasNext(); ) { + for (Field field : refType.fields()) { StringBuffer o = new StringBuffer(); - Field field = (Field)it.next(); o.append(" "); if (!refType.equals(refTypeBase)) { o.append(refType.name()); @@ -1666,14 +1613,13 @@ dump(obj, sup, refTypeBase); } } else if (refType instanceof InterfaceType) { - List sups = ((InterfaceType)refType).superinterfaces(); - for (Iterator it = sups.iterator(); it.hasNext(); ) { - dump(obj, (ReferenceType)it.next(), refTypeBase); + for (InterfaceType sup : ((InterfaceType)refType).superinterfaces()) { + dump(obj, sup, refTypeBase); } } else { /* else refType is an instanceof ArrayType */ if (obj instanceof ArrayReference) { - for (Iterator it = ((ArrayReference)obj).getValues().iterator(); + for (Iterator it = ((ArrayReference)obj).getValues().iterator(); it.hasNext(); ) { MessageOutput.printDirect(it.next().toString());// Special case: use printDirect() if (it.hasNext()) { @@ -1770,13 +1716,11 @@ new Object [] {owner.name(), new Integer (object.entryCount())}); } - List waiters = object.waitingThreads(); + List waiters = object.waitingThreads(); if (waiters.size() == 0) { MessageOutput.println("No waiters"); } else { - Iterator iter = waiters.iterator(); - while (iter.hasNext()) { - ThreadReference waiter = (ThreadReference)iter.next(); + for (ThreadReference waiter : waiters) { MessageOutput.println("Waiting thread:", waiter.name()); } } @@ -1800,13 +1744,11 @@ ThreadReference thread = threadInfo.getThread(); try { MessageOutput.println("Monitor information for thread", thread.name()); - List owned = thread.ownedMonitors(); + List owned = thread.ownedMonitors(); if (owned.size() == 0) { MessageOutput.println("No monitors owned"); } else { - Iterator iter = owned.iterator(); - while (iter.hasNext()) { - ObjectReference monitor = (ObjectReference)iter.next(); + for (ObjectReference monitor : owned) { MessageOutput.println("Owned monitor:", monitor.toString()); } } @@ -1833,9 +1775,7 @@ } String token = t.nextToken(); if (token.toLowerCase().equals("all")) { - Iterator iter = ThreadInfo.threads().iterator(); - while (iter.hasNext()) { - ThreadInfo threadInfo = (ThreadInfo)iter.next(); + for (ThreadInfo threadInfo : ThreadInfo.threads()) { printThreadLockInfo(threadInfo); } } else { @@ -1930,14 +1870,12 @@ void commandSave(final StringTokenizer t) { // Undocumented command: useful for testing. if (!t.hasMoreTokens()) { - Set keys = Env.getSaveKeys(); - Iterator iter = keys.iterator(); - if (!iter.hasNext()) { + Set keys = Env.getSaveKeys(); + if (keys.isEmpty()) { MessageOutput.println("No saved values"); return; } - while (iter.hasNext()) { - String key = (String)iter.next(); + for (String key : keys) { Value value = Env.getSavedValue(key); if ((value instanceof ObjectReference) && ((ObjectReference)value).isCollected()) { @@ -1976,7 +1914,7 @@ // Overloading is not handled here. String methodName = t.nextToken(); - List classes = Env.vm().classesByName(className); + List classes = Env.vm().classesByName(className); // TO DO: handle multiple classes found if (classes.size() == 0) { if (className.indexOf('.') < 0) { @@ -1987,17 +1925,14 @@ return; } - ReferenceType rt = (ReferenceType)classes.get(0); + ReferenceType rt = classes.get(0); if (!(rt instanceof ClassType)) { MessageOutput.println("not a class", className); return; } byte[] bytecodes = null; - List list = rt.methodsByName(methodName); - Iterator iter = list.iterator(); - while (iter.hasNext()) { - Method method = (Method)iter.next(); + for (Method method : rt.methodsByName(methodName)) { if (!method.isAbstract()) { bytecodes = method.bytecodes(); break; @@ -2047,7 +1982,7 @@ MessageOutput.println("Specify classes to redefine"); } else { String className = t.nextToken(); - List classes = Env.vm().classesByName(className); + List classes = Env.vm().classesByName(className); if (classes.size() == 0) { MessageOutput.println("No class named", className); return; @@ -2057,7 +1992,7 @@ return; } Env.setSourcePath(Env.getSourcePath()); - ReferenceType refType = (ReferenceType)classes.get(0); + ReferenceType refType = classes.get(0); if (!t.hasMoreTokens()) { MessageOutput.println("Specify file name for class", className); return; @@ -2074,7 +2009,8 @@ new Object [] {fileName, exc.toString()}); return; } - Map map = new HashMap(); + Map map + = new HashMap(); map.put(refType, bytes); try { Env.vm().redefineClasses(map); diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/tty/Env.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/tty/Env.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/tty/Env.java Tue Mar 11 23:37:02 2008 -0700 @@ -89,7 +89,7 @@ sourceCache.clear(); } - static void setSourcePath(List srcList) { + static void setSourcePath(List srcList) { sourceMapper = new SourceMapper(srcList); sourceCache.clear(); } @@ -106,10 +106,8 @@ } static String excludesString() { - Iterator iter = excludes().iterator(); StringBuffer buffer = new StringBuffer(); - while (iter.hasNext()) { - String pattern = (String)iter.next(); + for (String pattern : excludes()) { buffer.append(pattern); buffer.append(","); } @@ -117,25 +115,19 @@ } static void addExcludes(StepRequest request) { - Iterator iter = excludes().iterator(); - while (iter.hasNext()) { - String pattern = (String)iter.next(); + for (String pattern : excludes()) { request.addClassExclusionFilter(pattern); } } static void addExcludes(MethodEntryRequest request) { - Iterator iter = excludes().iterator(); - while (iter.hasNext()) { - String pattern = (String)iter.next(); + for (String pattern : excludes()) { request.addClassExclusionFilter(pattern); } } static void addExcludes(MethodExitRequest request) { - Iterator iter = excludes().iterator(); - while (iter.hasNext()) { - String pattern = (String)iter.next(); + for (String pattern : excludes()) { request.addClassExclusionFilter(pattern); } } @@ -175,10 +167,10 @@ try { String fileName = location.sourceName(); - Iterator iter = sourceCache.iterator(); + Iterator iter = sourceCache.iterator(); SourceCode code = null; while (iter.hasNext()) { - SourceCode candidate = (SourceCode)iter.next(); + SourceCode candidate = iter.next(); if (candidate.fileName().equals(fileName)) { code = candidate; iter.remove(); @@ -269,10 +261,7 @@ // loaded class whose name matches this limited regular // expression is selected. idToken = idToken.substring(1); - List classes = Env.vm().allClasses(); - Iterator iter = classes.iterator(); - while (iter.hasNext()) { - ReferenceType type = ((ReferenceType)iter.next()); + for (ReferenceType type : Env.vm().allClasses()) { if (type.name().endsWith(idToken)) { cls = type; break; @@ -280,21 +269,21 @@ } } else { // It's a class name - List classes = Env.vm().classesByName(idToken); + List classes = Env.vm().classesByName(idToken); if (classes.size() > 0) { // TO DO: handle multiples - cls = (ReferenceType)classes.get(0); + cls = classes.get(0); } } return cls; } - static Set getSaveKeys() { + static Set getSaveKeys() { return savedValues.keySet(); } static Value getSavedValue(String key) { - return (Value)savedValues.get(key); + return savedValues.get(key); } static void setSavedValue(String key, Value value) { @@ -327,7 +316,7 @@ if (index >= sourceLines.size()) { return null; } else { - return (String)sourceLines.get(index); + return sourceLines.get(index); } } } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/tty/EventHandler.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/tty/EventHandler.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/tty/EventHandler.java Tue Mar 11 23:37:02 2008 -0700 @@ -150,7 +150,7 @@ EventSet eventSet = queue.remove(); EventIterator iter = eventSet.eventIterator(); while (iter.hasNext()) { - handleExitEvent((Event)iter.next()); + handleExitEvent(iter.next()); } } catch (InterruptedException exc) { // ignore @@ -183,7 +183,7 @@ * If any event in the set has a thread associated with it, * they all will, so just grab the first one. */ - Event event = (Event)set.iterator().next(); // Is there a better way? + Event event = set.iterator().next(); // Is there a better way? thread = eventThread(event); } else { thread = null; diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/tty/EventRequestSpec.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/tty/EventRequestSpec.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/tty/EventRequestSpec.java Tue Mar 11 23:37:02 2008 -0700 @@ -101,10 +101,8 @@ * so that is all we need to examine. */ ArrayList deleteList = new ArrayList(); - Iterator iter = - Env.vm().eventRequestManager().exceptionRequests().iterator(); - while (iter.hasNext()) { - ExceptionRequest er = (ExceptionRequest)iter.next(); + for (ExceptionRequest er : + Env.vm().eventRequestManager().exceptionRequests()) { if (prs.matches(er.exception())) { deleteList.add (er); } @@ -115,9 +113,7 @@ } private EventRequest resolveAgainstPreparedClasses() throws Exception { - Iterator iter = Env.vm().allClasses().iterator(); - while (iter.hasNext()) { - ReferenceType refType = (ReferenceType)iter.next(); + for (ReferenceType refType : Env.vm().allClasses()) { if (refType.isPrepared() && refSpec.matches(refType)) { resolved = resolveEventRequest(refType); } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/tty/EventRequestSpecList.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/tty/EventRequestSpecList.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/tty/EventRequestSpecList.java Tue Mar 11 23:37:02 2008 -0700 @@ -55,9 +55,7 @@ boolean resolve(ClassPrepareEvent event) { boolean failure = false; synchronized(eventRequestSpecs) { - Iterator iter = eventRequestSpecs.iterator(); - while (iter.hasNext()) { - EventRequestSpec spec = (EventRequestSpec)iter.next(); + for (EventRequestSpec spec : eventRequestSpecs) { if (!spec.isResolved()) { try { EventRequest eventRequest = spec.resolve(event); @@ -77,9 +75,7 @@ } void resolveAll() { - Iterator iter = eventRequestSpecs.iterator(); - while (iter.hasNext()) { - EventRequestSpec spec = (EventRequestSpec)iter.next(); + for (EventRequestSpec spec : eventRequestSpecs) { try { EventRequest eventRequest = spec.resolveEagerly(); if (eventRequest != null) { @@ -106,16 +102,16 @@ } } - EventRequestSpec createBreakpoint(String classPattern, - int line) throws ClassNotFoundException { + BreakpointSpec createBreakpoint(String classPattern, int line) + throws ClassNotFoundException { ReferenceTypeSpec refSpec = new PatternReferenceTypeSpec(classPattern); return new BreakpointSpec(refSpec, line); } - EventRequestSpec createBreakpoint(String classPattern, + BreakpointSpec createBreakpoint(String classPattern, String methodId, - List methodArgs) + List methodArgs) throws MalformedMemberNameException, ClassNotFoundException { ReferenceTypeSpec refSpec = @@ -132,7 +128,7 @@ return new ExceptionSpec(refSpec, notifyCaught, notifyUncaught); } - EventRequestSpec createAccessWatchpoint(String classPattern, + WatchpointSpec createAccessWatchpoint(String classPattern, String fieldId) throws MalformedMemberNameException, ClassNotFoundException { @@ -141,7 +137,7 @@ return new AccessWatchpointSpec(refSpec, fieldId); } - EventRequestSpec createModificationWatchpoint(String classPattern, + WatchpointSpec createModificationWatchpoint(String classPattern, String fieldId) throws MalformedMemberNameException, ClassNotFoundException { @@ -154,7 +150,7 @@ synchronized (eventRequestSpecs) { int inx = eventRequestSpecs.indexOf(proto); if (inx != -1) { - EventRequestSpec spec = (EventRequestSpec)eventRequestSpecs.get(inx); + EventRequestSpec spec = eventRequestSpecs.get(inx); spec.remove(); eventRequestSpecs.remove(inx); return true; diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/tty/SourceMapper.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/tty/SourceMapper.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/tty/SourceMapper.java Tue Mar 11 23:37:02 2008 -0700 @@ -39,15 +39,13 @@ private final String[] dirs; - SourceMapper(List sourcepath) { + SourceMapper(List sourcepath) { /* * sourcepath can arrive from the debugee as a List. * (via PathSearchingVirtualMachine.classPath()) */ List dirList = new ArrayList(); - Iterator iter = sourcepath.iterator(); - while (iter.hasNext()) { - String element = (String)iter.next(); + for (String element : sourcepath) { //XXX remove .jar and .zip files; we want only directories on //the source path. (Bug ID 4186582) if ( ! (element.endsWith(".jar") || @@ -55,7 +53,7 @@ dirList.add(element); } } - dirs = (String[])dirList.toArray(new String[0]); + dirs = dirList.toArray(new String[0]); } SourceMapper(String sourcepath) { @@ -79,7 +77,7 @@ dirList.add(s); } } - dirs = (String[])dirList.toArray(new String[0]); + dirs = dirList.toArray(new String[0]); } /* diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/tty/TTY.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/tty/TTY.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/tty/TTY.java Tue Mar 11 23:37:02 2008 -0700 @@ -160,9 +160,7 @@ // here the next time. Env.setAtExitMethod(null); EventRequestManager erm = Env.vm().eventRequestManager(); - Iterator it = erm.methodExitRequests().iterator(); - while (it.hasNext()) { - EventRequest eReq = (EventRequest)it.next(); + for (EventRequest eReq : erm.methodExitRequests()) { if (eReq.equals(me.request())) { eReq.disable(); } @@ -178,9 +176,8 @@ public void vmInterrupted() { Thread.yield(); // fetch output printCurrentLocation(); - Iterator it = monitorCommands.iterator(); - while (it.hasNext()) { - StringTokenizer t = new StringTokenizer((String)it.next()); + for (String cmd : monitorCommands) { + StringTokenizer t = new StringTokenizer(cmd); t.nextToken(); // get rid of monitor number executeCommand(t); } @@ -563,9 +560,8 @@ ++monitorCount; monitorCommands.add(monitorCount + ": " + t.nextToken("")); } else { - Iterator it = monitorCommands.iterator(); - while (it.hasNext()) { - MessageOutput.printDirectln((String)it.next());// Special case: use printDirectln() + for (String cmd : monitorCommands) { + MessageOutput.printDirectln(cmd);// Special case: use printDirectln() } } } @@ -581,9 +577,7 @@ return; } String monStr = monTok + ":"; - Iterator it = monitorCommands.iterator(); - while (it.hasNext()) { - String cmd = (String)it.next(); + for (String cmd : monitorCommands) { StringTokenizer ct = new StringTokenizer(cmd); if (ct.nextToken().equals(monStr)) { monitorCommands.remove(cmd); @@ -768,10 +762,8 @@ } private static boolean supportsSharedMemory() { - List connectors = Bootstrap.virtualMachineManager().allConnectors(); - Iterator iter = connectors.iterator(); - while (iter.hasNext()) { - Connector connector = (Connector)iter.next(); + for (Connector connector : + Bootstrap.virtualMachineManager().allConnectors()) { if (connector.transport() == null) { continue; } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/tty/ThreadGroupIterator.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/tty/ThreadGroupIterator.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/tty/ThreadGroupIterator.java Tue Mar 11 23:37:02 2008 -0700 @@ -36,7 +36,7 @@ * Descend the tree of thread groups. * @author Robert G. Field */ -class ThreadGroupIterator implements Iterator { +class ThreadGroupIterator implements Iterator { private final Stack> stack = new Stack>(); ThreadGroupIterator(List tgl) { @@ -53,8 +53,8 @@ this(Env.vm().topLevelThreadGroups()); } - private Iterator top() { - return (Iterator)stack.peek(); + private Iterator top() { + return stack.peek(); } /** @@ -74,12 +74,12 @@ return !stack.isEmpty(); } - public Object next() { + public ThreadGroupReference next() { return nextThreadGroup(); } public ThreadGroupReference nextThreadGroup() { - ThreadGroupReference tg = (ThreadGroupReference)top().next(); + ThreadGroupReference tg = top().next(); push(tg.threadGroups()); return tg; } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/tty/ThreadInfo.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/tty/ThreadInfo.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/tty/ThreadInfo.java Tue Mar 11 23:37:02 2008 -0700 @@ -56,9 +56,7 @@ private static void initThreads() { if (!gotInitialThreads) { - Iterator iter = Env.vm().allThreads().iterator(); - while (iter.hasNext()) { - ThreadReference thread = (ThreadReference)iter.next(); + for (ThreadReference thread : Env.vm().allThreads()) { threads.add(new ThreadInfo(thread)); } gotInitialThreads = true; @@ -113,9 +111,7 @@ current = null; group = null; synchronized (threads) { - Iterator iter = threads().iterator(); - while (iter.hasNext()) { - ThreadInfo ti = (ThreadInfo)iter.next(); + for (ThreadInfo ti : threads()) { ti.invalidate(); } } @@ -163,8 +159,7 @@ if (group == null) { // Current thread group defaults to the first top level // thread group. - setThreadGroup((ThreadGroupReference) - Env.vm().topLevelThreadGroups().get(0)); + setThreadGroup(Env.vm().topLevelThreadGroups().get(0)); } return group; } @@ -173,9 +168,7 @@ ThreadInfo retInfo = null; synchronized (threads) { - Iterator iter = threads().iterator(); - while (iter.hasNext()) { - ThreadInfo ti = (ThreadInfo)iter.next(); + for (ThreadInfo ti : threads()) { if (ti.thread.uniqueID() == id) { retInfo = ti; break; @@ -208,7 +201,7 @@ * * @return a List of the stack frames. */ - List getStack() throws IncompatibleThreadStateException { + List getStack() throws IncompatibleThreadStateException { return thread.frames(); } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/tty/ThreadIterator.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/tty/ThreadIterator.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/tty/ThreadIterator.java Tue Mar 11 23:37:02 2008 -0700 @@ -30,8 +30,8 @@ import java.util.List; import java.util.Iterator; -class ThreadIterator implements Iterator { - Iterator it = null; +class ThreadIterator implements Iterator { + Iterator it = null; ThreadGroupIterator tgi; ThreadIterator(ThreadGroupReference tg) { @@ -56,12 +56,12 @@ return true; } - public Object next() { + public ThreadReference next() { return it.next(); } public ThreadReference nextThread() { - return (ThreadReference)next(); + return next(); } public void remove() { diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/example/debug/tty/VMConnection.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/tty/VMConnection.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/tty/VMConnection.java Tue Mar 11 23:37:02 2008 -0700 @@ -61,10 +61,8 @@ } private Connector findConnector(String name) { - List connectors = Bootstrap.virtualMachineManager().allConnectors(); - Iterator iter = connectors.iterator(); - while (iter.hasNext()) { - Connector connector = (Connector)iter.next(); + for (Connector connector : + Bootstrap.virtualMachineManager().allConnectors()) { if (connector.name().equals(name)) { return connector; } @@ -108,7 +106,7 @@ String value = token.substring(index + 1, token.length() - 1); // Remove comma delimiter - Connector.Argument argument = (Connector.Argument)arguments.get(name); + Connector.Argument argument = arguments.get(name); if (argument == null) { throw new IllegalArgumentException (MessageOutput.format("Argument is not defined for connector:", @@ -195,7 +193,7 @@ return false; } - Connector.Argument argument = (Connector.Argument)connectorArgs.get(name); + Connector.Argument argument = connectorArgs.get(name); if (argument == null) { return false; } @@ -204,7 +202,7 @@ } String connectorArg(String name) { - Connector.Argument argument = (Connector.Argument)connectorArgs.get(name); + Connector.Argument argument = connectorArgs.get(name); if (argument == null) { return ""; } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/hat/internal/server/ClassQuery.java --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/ClassQuery.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/ClassQuery.java Tue Mar 11 23:37:02 2008 -0700 @@ -99,8 +99,7 @@ } out.println("

Instance Data Members:

"); - JavaField[] ff = clazz.getFields(); - ff = (JavaField[]) ff.clone(); + JavaField[] ff = clazz.getFields().clone(); ArraySorter.sort(ff, new Comparer() { public int compare(Object lhs, Object rhs) { JavaField left = (JavaField) lhs; diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/hat/internal/server/PlatformClasses.java --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/PlatformClasses.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/PlatformClasses.java Tue Mar 11 23:37:02 2008 -0700 @@ -90,9 +90,7 @@ // is the right thing to do anyway. } } - int num = list.size(); - names = new String[num]; - names = (String[]) list.toArray(names); + names = list.toArray(new String[list.size()]); } return names; } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/jdi/AbstractLauncher.java --- a/jdk/src/share/classes/com/sun/tools/jdi/AbstractLauncher.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/jdi/AbstractLauncher.java Tue Mar 11 23:37:02 2008 -0700 @@ -119,7 +119,7 @@ String[] tokenArray = new String[tokenList.size()]; for (int i = 0; i < tokenList.size(); i++) { - tokenArray[i] = (String)tokenList.get(i); + tokenArray[i] = tokenList.get(i); } return tokenArray; } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/jdi/ClassTypeImpl.java --- a/jdk/src/share/classes/com/sun/tools/jdi/ClassTypeImpl.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/jdi/ClassTypeImpl.java Tue Mar 11 23:37:02 2008 -0700 @@ -95,11 +95,8 @@ } public List subclasses() { - List all = vm.allClasses(); List subs = new ArrayList(); - Iterator iter = all.iterator(); - while (iter.hasNext()) { - ReferenceType refType = (ReferenceType)iter.next(); + for (ReferenceType refType : vm.allClasses()) { if (refType instanceof ClassType) { ClassType clazz = (ClassType)refType; ClassType superclass = clazz.superclass(); @@ -223,7 +220,7 @@ List arguments = method.validateAndPrepareArgumentsForInvoke(origArguments); - ValueImpl[] args = (ValueImpl[])arguments.toArray(new ValueImpl[0]); + ValueImpl[] args = arguments.toArray(new ValueImpl[0]); JDWP.ClassType.InvokeMethod ret; try { PacketStream stream = @@ -271,7 +268,7 @@ List arguments = method.validateAndPrepareArgumentsForInvoke( origArguments); - ValueImpl[] args = (ValueImpl[])arguments.toArray(new ValueImpl[0]); + ValueImpl[] args = arguments.toArray(new ValueImpl[0]); JDWP.ClassType.NewInstance ret = null; try { PacketStream stream = @@ -301,11 +298,8 @@ } public Method concreteMethodByName(String name, String signature) { - List methods = visibleMethods(); Method method = null; - Iterator iter = methods.iterator(); - while (iter.hasNext()) { - Method candidate = (Method)iter.next(); + for (Method candidate : visibleMethods()) { if (candidate.name().equals(name) && candidate.signature().equals(signature) && !candidate.isAbstract()) { @@ -330,9 +324,7 @@ * Avoid duplicate checking on each method by iterating through * duplicate-free allInterfaces() rather than recursing */ - Iterator iter = allInterfaces().iterator(); - while (iter.hasNext()) { - InterfaceType interfaze = (InterfaceType)iter.next(); + for (InterfaceType interfaze : allInterfaces()) { list.addAll(interfaze.methods()); } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/jdi/ConcreteMethodImpl.java --- a/jdk/src/share/classes/com/sun/tools/jdi/ConcreteMethodImpl.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/jdi/ConcreteMethodImpl.java Tue Mar 11 23:37:02 2008 -0700 @@ -247,7 +247,7 @@ public byte[] bytecodes() { byte[] bytecodes = (bytecodesRef == null) ? null : - (byte[])bytecodesRef.get(); + bytecodesRef.get(); if (bytecodes == null) { try { bytecodes = JDWP.Method.Bytecodes. @@ -262,7 +262,7 @@ * to return the cached bytecodes directly; instead, we * make a clone at the cost of using more memory. */ - return (byte[])bytecodes.clone(); + return bytecodes.clone(); } int argSlotCount() throws AbsentInformationException { @@ -279,7 +279,7 @@ String stratumID = stratum.id(); SoftLocationXRefs info = (softOtherLocationXRefsRef == null) ? null : - (SoftLocationXRefs)softOtherLocationXRefsRef.get(); + softOtherLocationXRefsRef.get(); if (info != null && info.stratumID.equals(stratumID)) { return info; } @@ -348,7 +348,7 @@ private SoftLocationXRefs getBaseLocations() { SoftLocationXRefs info = (softBaseLocationXRefsRef == null) ? null : - (SoftLocationXRefs)softBaseLocationXRefsRef.get(); + softBaseLocationXRefsRef.get(); if (info != null) { return info; } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/jdi/EventSetImpl.java --- a/jdk/src/share/classes/com/sun/tools/jdi/EventSetImpl.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/jdi/EventSetImpl.java Tue Mar 11 23:37:02 2008 -0700 @@ -56,10 +56,8 @@ public String toString() { String string = "event set, policy:" + suspendPolicy + ", count:" + this.size() + " = {"; - Iterator iter = this.iterator(); boolean first = true; - while (iter.hasNext()) { - Event event = (Event)iter.next(); + for (Event event : this) { if (!first) { string += ", "; } @@ -787,9 +785,7 @@ } private ThreadReference eventThread() { - Iterator iter = this.iterator(); - while (iter.hasNext()) { - Event event = (Event)iter.next(); + for (Event event : this) { if (event instanceof ThreadedEventImpl) { return ((ThreadedEventImpl)event).thread(); } @@ -846,7 +842,7 @@ } public Event nextEvent() { - return (Event)next(); + return next(); } public void remove() { diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/jdi/JNITypeParser.java --- a/jdk/src/share/classes/com/sun/tools/jdi/JNITypeParser.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/jdi/JNITypeParser.java Tue Mar 11 23:37:02 2008 -0700 @@ -82,7 +82,7 @@ } String typeName() { - return (String)typeNameList().get(typeNameList().size()-1); + return typeNameList().get(typeNameList().size()-1); } List argumentTypeNames() { @@ -90,7 +90,7 @@ } String signature() { - return (String)signatureList().get(signatureList().size()-1); + return signatureList().get(signatureList().size()-1); } List argumentSignatures() { diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/jdi/MethodImpl.java --- a/jdk/src/share/classes/com/sun/tools/jdi/MethodImpl.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/jdi/MethodImpl.java Tue Mar 11 23:37:02 2008 -0700 @@ -158,7 +158,7 @@ Type argumentType(int index) throws ClassNotLoadedException { ReferenceTypeImpl enclosing = (ReferenceTypeImpl)declaringType(); - String signature = (String)argumentSignatures().get(index); + String signature = argumentSignatures().get(index); return enclosing.findType(signature); } @@ -263,10 +263,10 @@ return argumentType(index); } public String typeName(){ - return (String)argumentTypeNames().get(index); + return argumentTypeNames().get(index); } public String signature() { - return (String)argumentSignatures().get(index); + return argumentSignatures().get(index); } public Type findType(String signature) throws ClassNotLoadedException { return MethodImpl.this.findType(signature); @@ -307,7 +307,7 @@ arguments.add(argArray); return; } - Value nthArgValue = (Value)arguments.get(paramCount - 1); + Value nthArgValue = arguments.get(paramCount - 1); if (nthArgValue == null) { return; } @@ -371,7 +371,7 @@ } for (int i = 0; i < argSize; i++) { - Value value = (Value)arguments.get(i); + Value value = arguments.get(i); value = ValueImpl.prepareForAssignment(value, new ArgumentContainer(i)); arguments.set(i, value); @@ -386,11 +386,11 @@ sb.append(name()); sb.append("("); boolean first = true; - for (Iterator it = argumentTypeNames().iterator(); it.hasNext();) { + for (String name : argumentTypeNames()) { if (!first) { sb.append(", "); } - sb.append((String)it.next()); + sb.append(name); first = false; } sb.append(")"); diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java --- a/jdk/src/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java Tue Mar 11 23:37:02 2008 -0700 @@ -383,7 +383,7 @@ List arguments = method.validateAndPrepareArgumentsForInvoke( origArguments); - ValueImpl[] args = (ValueImpl[])arguments.toArray(new ValueImpl[0]); + ValueImpl[] args = arguments.toArray(new ValueImpl[0]); JDWP.ObjectReference.InvokeMethod ret; try { PacketStream stream = @@ -583,7 +583,7 @@ // Validate assignment ReferenceType destType = (ReferenceTypeImpl)destination.type(); ReferenceTypeImpl myType = (ReferenceTypeImpl)referenceType(); - if (!myType.isAssignableTo((ReferenceType)destType)) { + if (!myType.isAssignableTo(destType)) { JNITypeParser parser = new JNITypeParser(destType.signature()); String destTypeName = parser.typeName(); throw new InvalidTypeException("Can't assign " + diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/jdi/PacketStream.java --- a/jdk/src/share/classes/com/sun/tools/jdi/PacketStream.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/jdi/PacketStream.java Tue Mar 11 23:37:02 2008 -0700 @@ -485,7 +485,7 @@ * Read field represented as vm specific byte sequence. */ Field readField() { - ReferenceTypeImpl refType = (ReferenceTypeImpl)readReferenceType(); + ReferenceTypeImpl refType = readReferenceType(); long fieldRef = readFieldRef(); return refType.getFieldMirror(fieldRef); } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/jdi/ReferenceTypeImpl.java --- a/jdk/src/share/classes/com/sun/tools/jdi/ReferenceTypeImpl.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/jdi/ReferenceTypeImpl.java Tue Mar 11 23:37:02 2008 -0700 @@ -59,7 +59,7 @@ private boolean constantPoolInfoGotten = false; private int constanPoolCount; private byte[] constantPoolBytes; - private SoftReference constantPoolBytesRef = null; + private SoftReference constantPoolBytesRef = null; /* to mark a SourceFile request that returned a genuine JDWP.Error.ABSENT_INFORMATION */ private static final String ABSENT_BASE_SOURCE_NAME = "**ABSENT_BASE_SOURCE_NAME**"; @@ -352,13 +352,10 @@ abstract List inheritedTypes(); void addVisibleFields(List visibleList, Map visibleTable, List ambiguousNames) { - List list = visibleFields(); - Iterator iter = list.iterator(); - while (iter.hasNext()) { - Field field = (Field)iter.next(); + for (Field field : visibleFields()) { String name = field.name(); if (!ambiguousNames.contains(name)) { - Field duplicate = (Field)visibleTable.get(name); + Field duplicate = visibleTable.get(name); if (duplicate == null) { visibleList.add(field); visibleTable.put(name, field); @@ -402,10 +399,8 @@ * hide. */ List retList = new ArrayList(fields()); - iter = retList.iterator(); - while (iter.hasNext()) { - Field field = (Field)iter.next(); - Field hidden = (Field)visibleTable.get(field.name()); + for (Field field : retList) { + Field hidden = visibleTable.get(field.name()); if (hidden != null) { visibleList.remove(hidden); } @@ -515,12 +510,9 @@ * methods. */ void addToMethodMap(Map methodMap, List methodList) { - Iterator iter = methodList.iterator(); - while (iter.hasNext()) { - Method method = (Method)iter.next(); + for (Method method : methodList) methodMap.put(method.name().concat(method.signature()), method); } - } abstract void addVisibleMethods(Map methodMap); @@ -549,9 +541,7 @@ public List methodsByName(String name) { List methods = visibleMethods(); ArrayList retList = new ArrayList(methods.size()); - Iterator iter = methods.iterator(); - while (iter.hasNext()) { - Method candidate = (Method)iter.next(); + for (Method candidate : methods) { if (candidate.name().equals(name)) { retList.add(candidate); } @@ -563,9 +553,7 @@ public List methodsByName(String name, String signature) { List methods = visibleMethods(); ArrayList retList = new ArrayList(methods.size()); - Iterator iter = methods.iterator(); - while (iter.hasNext()) { - Method candidate = (Method)iter.next(); + for (Method candidate : methods) { if (candidate.name().equals(name) && candidate.signature().equals(signature)) { retList.add(candidate); @@ -706,7 +694,7 @@ } public String sourceName() throws AbsentInformationException { - return (String)(sourceNames(vm.getDefaultStratum()).get(0)); + return sourceNames(vm.getDefaultStratum()).get(0); } public List sourceNames(String stratumID) @@ -796,7 +784,7 @@ if (!vm.canGetSourceDebugExtension()) { return NO_SDE_INFO_MARK; } - SDE sde = (sdeRef == null) ? null : (SDE)sdeRef.get(); + SDE sde = (sdeRef == null) ? null : sdeRef.get(); if (sde == null) { String extension = null; try { @@ -1034,13 +1022,13 @@ throw exc; } if (constantPoolBytesRef != null) { - byte[] cpbytes = (byte[])constantPoolBytesRef.get(); + byte[] cpbytes = constantPoolBytesRef.get(); /* * Arrays are always modifiable, so it is a little unsafe * to return the cached bytecodes directly; instead, we * make a clone at the cost of using more memory. */ - return (byte[])cpbytes.clone(); + return cpbytes.clone(); } else { return null; } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/jdi/SDE.java --- a/jdk/src/share/classes/com/sun/tools/jdi/SDE.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/jdi/SDE.java Tue Mar 11 23:37:02 2008 -0700 @@ -327,7 +327,7 @@ ignoreWhite(); while (((ch = sdeRead()) != '\n') && (ch != '\r')) { - sb.append((char)ch); + sb.append(ch); } // check for CR LF if ((ch == '\r') && (sdePeek() == '\n')) { diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/jdi/StackFrameImpl.java --- a/jdk/src/share/classes/com/sun/tools/jdi/StackFrameImpl.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/jdi/StackFrameImpl.java Tue Mar 11 23:37:02 2008 -0700 @@ -162,7 +162,7 @@ for (LocalVariable variable : allVariables) { String name = variable.name(); if (variable.isVisible(this)) { - LocalVariable existing = (LocalVariable)map.get(name); + LocalVariable existing = map.get(name); if ((existing == null) || ((LocalVariableImpl)variable).hides(existing)) { map.put(name, variable); @@ -330,7 +330,7 @@ slot = 1; } for (int ii = 0; ii < count; ++ii) { - char sigChar = (char)argSigs.get(ii).charAt(0); + char sigChar = argSigs.get(ii).charAt(0); slots[ii] = new JDWP.StackFrame.GetValues.SlotInfo(slot++,(byte)sigChar); if (sigChar == 'J' || sigChar == 'D') { slot++; diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/jdi/TargetVM.java --- a/jdk/src/share/classes/com/sun/tools/jdi/TargetVM.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/jdi/TargetVM.java Tue Mar 11 23:37:02 2008 -0700 @@ -148,7 +148,7 @@ idString = String.valueOf(p.id); synchronized(waitingQueue) { - p2 = (Packet)waitingQueue.get(idString); + p2 = waitingQueue.get(idString); if (p2 != null) waitingQueue.remove(idString); diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/jdi/ThreadGroupReferenceImpl.java --- a/jdk/src/share/classes/com/sun/tools/jdi/ThreadGroupReferenceImpl.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/jdi/ThreadGroupReferenceImpl.java Tue Mar 11 23:37:02 2008 -0700 @@ -86,30 +86,22 @@ } public void suspend() { - List threads = threads(); - Iterator iter = threads.iterator(); - while (iter.hasNext()) { - ((ThreadReference)iter.next()).suspend(); + for (ThreadReference thread : threads()) { + thread.suspend(); } - List groups = threadGroups(); - iter = groups.iterator(); - while (iter.hasNext()) { - ((ThreadGroupReference)iter.next()).suspend(); + for (ThreadGroupReference threadGroup : threadGroups()) { + threadGroup.suspend(); } } public void resume() { - List threads = threads(); - Iterator iter = threads.iterator(); - while (iter.hasNext()) { - ((ThreadReference)iter.next()).resume(); + for (ThreadReference thread : threads()) { + thread.resume(); } - List groups = threadGroups(); - iter = groups.iterator(); - while (iter.hasNext()) { - ((ThreadGroupReference)iter.next()).resume(); + for (ThreadGroupReference threadGroup : threadGroups()) { + threadGroup.resume(); } } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java --- a/jdk/src/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java Tue Mar 11 23:37:02 2008 -0700 @@ -1191,8 +1191,7 @@ } requests = new JDWP.VirtualMachine.DisposeObjects.Request[size]; for (int i = 0; i < requests.length; i++) { - SoftObjectReference ref = - (SoftObjectReference)batchedDisposeRequests.get(i); + SoftObjectReference ref = batchedDisposeRequests.get(i); if ((traceFlags & TRACE_OBJREFS) != 0) { printTrace("Disposing object " + ref.key().longValue() + " (ref count = " + ref.count() + ")"); @@ -1436,7 +1435,7 @@ } ObjectReferenceImpl object() { - return (ObjectReferenceImpl)get(); + return get(); } } } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java --- a/jdk/src/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java Tue Mar 11 23:37:02 2008 -0700 @@ -92,7 +92,7 @@ Connector connector; try { - connector = (Connector)connectors.next(); + connector = connectors.next(); } catch (ThreadDeath x) { throw x; } catch (Exception x) { @@ -121,7 +121,7 @@ TransportService transportService; try { - transportService = (TransportService)transportServices.next(); + transportService = transportServices.next(); } catch (ThreadDeath x) { throw x; } catch (Exception x) { diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/io/FileInputStream.java --- a/jdk/src/share/classes/java/io/FileInputStream.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/io/FileInputStream.java Tue Mar 11 23:37:02 2008 -0700 @@ -48,15 +48,15 @@ class FileInputStream extends InputStream { /* File Descriptor - handle to the open file */ - private FileDescriptor fd; + private final FileDescriptor fd; private FileChannel channel = null; - private Object closeLock = new Object(); + private final Object closeLock = new Object(); private volatile boolean closed = false; - private static ThreadLocal runningFinalize = - new ThreadLocal(); + private static final ThreadLocal runningFinalize = + new ThreadLocal(); private static boolean isRunningFinalize() { Boolean val; @@ -151,7 +151,7 @@ * is thrown. *

* This constructor does not throw an exception if fdObj - * is {link java.io.FileDescriptor#valid() invalid}. + * is {@link java.io.FileDescriptor#valid() invalid}. * However, if the methods are invoked on the resulting stream to attempt * I/O on the stream, an IOException is thrown. * @@ -389,7 +389,7 @@ * @see java.io.FileInputStream#close() */ protected void finalize() throws IOException { - if ((fd != null) && (fd != fd.in)) { + if ((fd != null) && (fd != FileDescriptor.in)) { /* * Finalizer should not release the FileDescriptor if another diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/io/FileOutputStream.java --- a/jdk/src/share/classes/java/io/FileOutputStream.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/io/FileOutputStream.java Tue Mar 11 23:37:02 2008 -0700 @@ -52,20 +52,16 @@ class FileOutputStream extends OutputStream { /** - * The system dependent file descriptor. The value is - * 1 more than actual file descriptor. This means that - * the default value 0 indicates that the file is not open. + * The system dependent file descriptor. */ - private FileDescriptor fd; + private final FileDescriptor fd; private FileChannel channel= null; - private boolean append = false; - - private Object closeLock = new Object(); + private final Object closeLock = new Object(); private volatile boolean closed = false; - private static ThreadLocal runningFinalize = - new ThreadLocal(); + private static final ThreadLocal runningFinalize = + new ThreadLocal(); private static boolean isRunningFinalize() { Boolean val; @@ -75,7 +71,7 @@ } /** - * Creates an output file stream to write to the file with the + * Creates a file output stream to write to the file with the * specified name. A new FileDescriptor object is * created to represent this file connection. *

@@ -100,8 +96,8 @@ } /** - * Creates an output file stream to write to the file with the specified - * name. If the second argument is true, then + * Creates a file output stream to write to the file with the specified + * name. If the second argument is true, then * bytes will be written to the end of the file rather than the beginning. * A new FileDescriptor object is created to represent this * file connection. @@ -202,16 +198,11 @@ } fd = new FileDescriptor(); fd.incrementAndGetUseCount(); - this.append = append; - if (append) { - openAppend(name); - } else { - open(name); - } + open(name, append); } /** - * Creates an output file stream to write to the specified file + * Creates a file output stream to write to the specified file * descriptor, which represents an existing connection to an actual * file in the file system. *

@@ -223,7 +214,7 @@ * is thrown. *

* This constructor does not throw an exception if fdObj - * is {link java.io.FileDescriptor#valid() invalid}. + * is {@link java.io.FileDescriptor#valid() invalid}. * However, if the methods are invoked on the resulting stream to attempt * I/O on the stream, an IOException is thrown. * @@ -252,16 +243,12 @@ } /** - * Opens a file, with the specified name, for writing. + * Opens a file, with the specified name, for overwriting or appending. * @param name name of file to be opened + * @param append whether the file is to be opened in append mode */ - private native void open(String name) throws FileNotFoundException; - - /** - * Opens a file, with the specified name, for appending. - * @param name name of file to be opened - */ - private native void openAppend(String name) throws FileNotFoundException; + private native void open(String name, boolean append) + throws FileNotFoundException; /** * Writes the specified byte to this file output stream. Implements @@ -385,7 +372,7 @@ public FileChannel getChannel() { synchronized (this) { if (channel == null) { - channel = FileChannelImpl.open(fd, false, true, this, append); + channel = FileChannelImpl.open(fd, false, true, this); /* * Increment fd's use count. Invoking the channel's close() @@ -408,7 +395,7 @@ */ protected void finalize() throws IOException { if (fd != null) { - if (fd == fd.out || fd == fd.err) { + if (fd == FileDescriptor.out || fd == FileDescriptor.err) { flush(); } else { diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/io/ObjectInputStream.java --- a/jdk/src/share/classes/java/io/ObjectInputStream.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/io/ObjectInputStream.java Tue Mar 11 23:37:02 2008 -0700 @@ -212,7 +212,8 @@ private static final Object unsharedMarker = new Object(); /** table mapping primitive type names to corresponding class objects */ - private static final HashMap primClasses = new HashMap(8, 1.0F); + private static final HashMap> primClasses + = new HashMap>(8, 1.0F); static { primClasses.put("boolean", boolean.class); primClasses.put("byte", byte.class); @@ -620,7 +621,7 @@ try { return Class.forName(name, false, latestUserDefinedLoader()); } catch (ClassNotFoundException ex) { - Class cl = (Class) primClasses.get(name); + Class cl = primClasses.get(name); if (cl != null) { return cl; } else { @@ -1254,11 +1255,11 @@ * override security-sensitive non-final methods. Returns true if subclass * is "safe", false otherwise. */ - private static boolean auditSubclass(final Class subcl) { + private static boolean auditSubclass(final Class subcl) { Boolean result = AccessController.doPrivileged( new PrivilegedAction() { public Boolean run() { - for (Class cl = subcl; + for (Class cl = subcl; cl != ObjectInputStream.class; cl = cl.getSuperclass()) { @@ -2217,9 +2218,9 @@ try { while (list != null) { AccessController.doPrivileged( - new PrivilegedExceptionAction() + new PrivilegedExceptionAction() { - public Object run() throws InvalidObjectException { + public Void run() throws InvalidObjectException { list.obj.validateObject(); return null; } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/io/ObjectStreamClass.java --- a/jdk/src/share/classes/java/io/ObjectStreamClass.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/io/ObjectStreamClass.java Tue Mar 11 23:37:02 2008 -0700 @@ -77,7 +77,7 @@ NO_FIELDS; /** reflection factory for obtaining serialization constructors */ - private static final ReflectionFactory reflFactory = (ReflectionFactory) + private static final ReflectionFactory reflFactory = AccessController.doPrivileged( new ReflectionFactory.GetReflectionFactoryAction()); @@ -216,10 +216,10 @@ public long getSerialVersionUID() { // REMIND: synchronize instead of relying on volatile? if (suid == null) { - suid = (Long) AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { - return Long.valueOf(computeDefaultSUID(cl)); + suid = AccessController.doPrivileged( + new PrivilegedAction() { + public Long run() { + return computeDefaultSUID(cl); } } ); @@ -392,8 +392,8 @@ } if (interrupted) { AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { + new PrivilegedAction() { + public Void run() { Thread.currentThread().interrupt(); return null; } @@ -427,8 +427,8 @@ localDesc = this; if (serializable) { - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { if (isEnum) { suid = Long.valueOf(0); fields = NO_FIELDS; @@ -802,7 +802,7 @@ * non-primitive types, and any other non-null type matches assignable * types only. Returns matching field, or null if no match found. */ - ObjectStreamField getField(String name, Class type) { + ObjectStreamField getField(String name, Class type) { for (int i = 0; i < fields.length; i++) { ObjectStreamField f = fields[i]; if (f.getName().equals(name)) { @@ -811,7 +811,7 @@ { return f; } - Class ftype = f.getType(); + Class ftype = f.getType(); if (ftype != null && type.isAssignableFrom(ftype)) { return f; } @@ -1130,7 +1130,7 @@ private ClassDataSlot[] getClassDataLayout0() throws InvalidClassException { - ArrayList slots = new ArrayList(); + ArrayList slots = new ArrayList(); Class start = cl, end = cl; // locate closest non-serializable superclass @@ -1171,8 +1171,7 @@ // order slots from superclass -> subclass Collections.reverse(slots); - return (ClassDataSlot[]) - slots.toArray(new ClassDataSlot[slots.size()]); + return slots.toArray(new ClassDataSlot[slots.size()]); } /** @@ -1309,9 +1308,9 @@ * Access checks are disabled on the returned constructor (if any), since * the defining class may still be non-public. */ - private static Constructor getExternalizableConstructor(Class cl) { + private static Constructor getExternalizableConstructor(Class cl) { try { - Constructor cons = cl.getDeclaredConstructor((Class[]) null); + Constructor cons = cl.getDeclaredConstructor((Class[]) null); cons.setAccessible(true); return ((cons.getModifiers() & Modifier.PUBLIC) != 0) ? cons : null; @@ -1325,15 +1324,15 @@ * superclass, or null if none found. Access checks are disabled on the * returned constructor (if any). */ - private static Constructor getSerializableConstructor(Class cl) { - Class initCl = cl; + private static Constructor getSerializableConstructor(Class cl) { + Class initCl = cl; while (Serializable.class.isAssignableFrom(initCl)) { if ((initCl = initCl.getSuperclass()) == null) { return null; } } try { - Constructor cons = initCl.getDeclaredConstructor((Class[]) null); + Constructor cons = initCl.getDeclaredConstructor((Class[]) null); int mods = cons.getModifiers(); if ((mods & Modifier.PRIVATE) != 0 || ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 && @@ -1355,12 +1354,12 @@ * null if no match found. Access checks are disabled on the returned * method (if any). */ - private static Method getInheritableMethod(Class cl, String name, + private static Method getInheritableMethod(Class cl, String name, Class[] argTypes, Class returnType) { Method meth = null; - Class defCl = cl; + Class defCl = cl; while (defCl != null) { try { meth = defCl.getDeclaredMethod(name, argTypes); @@ -1391,9 +1390,9 @@ * class, or null if none found. Access checks are disabled on the * returned method (if any). */ - private static Method getPrivateMethod(Class cl, String name, - Class[] argTypes, - Class returnType) + private static Method getPrivateMethod(Class cl, String name, + Class[] argTypes, + Class returnType) { try { Method meth = cl.getDeclaredMethod(name, argTypes); @@ -1567,7 +1566,7 @@ ObjectStreamField[] boundFields = new ObjectStreamField[serialPersistentFields.length]; - Set fieldNames = new HashSet(serialPersistentFields.length); + Set fieldNames = new HashSet(serialPersistentFields.length); for (int i = 0; i < serialPersistentFields.length; i++) { ObjectStreamField spf = serialPersistentFields[i]; @@ -1605,7 +1604,7 @@ */ private static ObjectStreamField[] getDefaultSerialFields(Class cl) { Field[] clFields = cl.getDeclaredFields(); - ArrayList list = new ArrayList(); + ArrayList list = new ArrayList(); int mask = Modifier.STATIC | Modifier.TRANSIENT; for (int i = 0; i < clFields.length; i++) { @@ -1615,7 +1614,7 @@ } int size = list.size(); return (size == 0) ? NO_FIELDS : - (ObjectStreamField[]) list.toArray(new ObjectStreamField[size]); + list.toArray(new ObjectStreamField[size]); } /** @@ -1688,11 +1687,9 @@ for (int i = 0; i < fields.length; i++) { fieldSigs[i] = new MemberSignature(fields[i]); } - Arrays.sort(fieldSigs, new Comparator() { - public int compare(Object o1, Object o2) { - String name1 = ((MemberSignature) o1).name; - String name2 = ((MemberSignature) o2).name; - return name1.compareTo(name2); + Arrays.sort(fieldSigs, new Comparator() { + public int compare(MemberSignature ms1, MemberSignature ms2) { + return ms1.name.compareTo(ms2.name); } }); for (int i = 0; i < fieldSigs.length; i++) { @@ -1721,11 +1718,9 @@ for (int i = 0; i < cons.length; i++) { consSigs[i] = new MemberSignature(cons[i]); } - Arrays.sort(consSigs, new Comparator() { - public int compare(Object o1, Object o2) { - String sig1 = ((MemberSignature) o1).signature; - String sig2 = ((MemberSignature) o2).signature; - return sig1.compareTo(sig2); + Arrays.sort(consSigs, new Comparator() { + public int compare(MemberSignature ms1, MemberSignature ms2) { + return ms1.signature.compareTo(ms2.signature); } }); for (int i = 0; i < consSigs.length; i++) { @@ -1746,10 +1741,8 @@ for (int i = 0; i < methods.length; i++) { methSigs[i] = new MemberSignature(methods[i]); } - Arrays.sort(methSigs, new Comparator() { - public int compare(Object o1, Object o2) { - MemberSignature ms1 = (MemberSignature) o1; - MemberSignature ms2 = (MemberSignature) o2; + Arrays.sort(methSigs, new Comparator() { + public int compare(MemberSignature ms1, MemberSignature ms2) { int comp = ms1.name.compareTo(ms2.name); if (comp == 0) { comp = ms1.signature.compareTo(ms2.signature); @@ -1859,7 +1852,7 @@ keys = new long[nfields]; offsets = new int[nfields]; typeCodes = new char[nfields]; - ArrayList typeList = new ArrayList(); + ArrayList> typeList = new ArrayList>(); for (int i = 0; i < nfields; i++) { ObjectStreamField f = fields[i]; @@ -1873,7 +1866,7 @@ } } - types = (Class[]) typeList.toArray(new Class[typeList.size()]); + types = typeList.toArray(new Class[typeList.size()]); numPrimFields = nfields - types.length; } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/lang/Class.java --- a/jdk/src/share/classes/java/lang/Class.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/lang/Class.java Tue Mar 11 23:37:02 2008 -0700 @@ -345,9 +345,9 @@ // since we have to do the security check here anyway // (the stack depth is wrong for the Constructor's // security check to work) - java.security.AccessController.doPrivileged - (new java.security.PrivilegedAction() { - public Object run() { + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { c.setAccessible(true); return null; } @@ -1302,10 +1302,10 @@ // out anything other than public members and (2) public member access // has already been ok'd by the SecurityManager. - Class[] result = (Class[]) java.security.AccessController.doPrivileged - (new java.security.PrivilegedAction() { - public Object run() { - java.util.List list = new java.util.ArrayList(); + return java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Class[] run() { + List list = new ArrayList(); Class currentClass = Class.this; while (currentClass != null) { Class[] members = currentClass.getDeclaredClasses(); @@ -1316,12 +1316,9 @@ } currentClass = currentClass.getSuperclass(); } - Class[] empty = {}; - return list.toArray(empty); + return list.toArray(new Class[0]); } }); - - return result; } @@ -2215,15 +2212,15 @@ // Caches for certain reflective results private static boolean useCaches = true; - private volatile transient SoftReference declaredFields; - private volatile transient SoftReference publicFields; - private volatile transient SoftReference declaredMethods; - private volatile transient SoftReference publicMethods; - private volatile transient SoftReference declaredConstructors; - private volatile transient SoftReference publicConstructors; + private volatile transient SoftReference declaredFields; + private volatile transient SoftReference publicFields; + private volatile transient SoftReference declaredMethods; + private volatile transient SoftReference publicMethods; + private volatile transient SoftReference[]> declaredConstructors; + private volatile transient SoftReference[]> publicConstructors; // Intermediate results for getFields and getMethods - private volatile transient SoftReference declaredPublicFields; - private volatile transient SoftReference declaredPublicMethods; + private volatile transient SoftReference declaredPublicFields; + private volatile transient SoftReference declaredPublicMethods; // Incremented by the VM on each call to JVM TI RedefineClasses() // that redefines this class or a superclass. @@ -2295,11 +2292,11 @@ clearCachesOnClassRedefinition(); if (publicOnly) { if (declaredPublicFields != null) { - res = (Field[]) declaredPublicFields.get(); + res = declaredPublicFields.get(); } } else { if (declaredFields != null) { - res = (Field[]) declaredFields.get(); + res = declaredFields.get(); } } if (res != null) return res; @@ -2308,9 +2305,9 @@ res = Reflection.filterFields(this, getDeclaredFields0(publicOnly)); if (useCaches) { if (publicOnly) { - declaredPublicFields = new SoftReference(res); + declaredPublicFields = new SoftReference(res); } else { - declaredFields = new SoftReference(res); + declaredFields = new SoftReference(res); } } return res; @@ -2319,22 +2316,22 @@ // Returns an array of "root" fields. These Field objects must NOT // be propagated to the outside world, but must instead be copied // via ReflectionFactory.copyField. - private Field[] privateGetPublicFields(Set traversedInterfaces) { + private Field[] privateGetPublicFields(Set> traversedInterfaces) { checkInitted(); Field[] res = null; if (useCaches) { clearCachesOnClassRedefinition(); if (publicFields != null) { - res = (Field[]) publicFields.get(); + res = publicFields.get(); } if (res != null) return res; } // No cached value available; compute value recursively. // Traverse in correct order for getField(). - List fields = new ArrayList(); + List fields = new ArrayList(); if (traversedInterfaces == null) { - traversedInterfaces = new HashSet(); + traversedInterfaces = new HashSet>(); } // Local fields @@ -2342,9 +2339,7 @@ addAll(fields, tmp); // Direct superinterfaces, recursively - Class[] interfaces = getInterfaces(); - for (int i = 0; i < interfaces.length; i++) { - Class c = interfaces[i]; + for (Class c : getInterfaces()) { if (!traversedInterfaces.contains(c)) { traversedInterfaces.add(c); addAll(fields, c.privateGetPublicFields(traversedInterfaces)); @@ -2353,7 +2348,7 @@ // Direct superclass, recursively if (!isInterface()) { - Class c = getSuperclass(); + Class c = getSuperclass(); if (c != null) { addAll(fields, c.privateGetPublicFields(traversedInterfaces)); } @@ -2362,12 +2357,12 @@ res = new Field[fields.size()]; fields.toArray(res); if (useCaches) { - publicFields = new SoftReference(res); + publicFields = new SoftReference(res); } return res; } - private static void addAll(Collection c, Field[] o) { + private static void addAll(Collection c, Field[] o) { for (int i = 0; i < o.length; i++) { c.add(o[i]); } @@ -2383,18 +2378,18 @@ // Returns an array of "root" constructors. These Constructor // objects must NOT be propagated to the outside world, but must // instead be copied via ReflectionFactory.copyConstructor. - private Constructor[] privateGetDeclaredConstructors(boolean publicOnly) { + private Constructor[] privateGetDeclaredConstructors(boolean publicOnly) { checkInitted(); - Constructor[] res = null; + Constructor[] res = null; if (useCaches) { clearCachesOnClassRedefinition(); if (publicOnly) { if (publicConstructors != null) { - res = (Constructor[]) publicConstructors.get(); + res = publicConstructors.get(); } } else { if (declaredConstructors != null) { - res = (Constructor[]) declaredConstructors.get(); + res = declaredConstructors.get(); } } if (res != null) return res; @@ -2407,9 +2402,9 @@ } if (useCaches) { if (publicOnly) { - publicConstructors = new SoftReference(res); + publicConstructors = new SoftReference[]>(res); } else { - declaredConstructors = new SoftReference(res); + declaredConstructors = new SoftReference[]>(res); } } return res; @@ -2431,11 +2426,11 @@ clearCachesOnClassRedefinition(); if (publicOnly) { if (declaredPublicMethods != null) { - res = (Method[]) declaredPublicMethods.get(); + res = declaredPublicMethods.get(); } } else { if (declaredMethods != null) { - res = (Method[]) declaredMethods.get(); + res = declaredMethods.get(); } } if (res != null) return res; @@ -2444,9 +2439,9 @@ res = Reflection.filterMethods(this, getDeclaredMethods0(publicOnly)); if (useCaches) { if (publicOnly) { - declaredPublicMethods = new SoftReference(res); + declaredPublicMethods = new SoftReference(res); } else { - declaredMethods = new SoftReference(res); + declaredMethods = new SoftReference(res); } } return res; @@ -2552,7 +2547,7 @@ if (useCaches) { clearCachesOnClassRedefinition(); if (publicMethods != null) { - res = (Method[]) publicMethods.get(); + res = publicMethods.get(); } if (res != null) return res; } @@ -2602,7 +2597,7 @@ methods.compactAndTrim(); res = methods.getArray(); if (useCaches) { - publicMethods = new SoftReference(res); + publicMethods = new SoftReference(res); } return res; } @@ -2713,11 +2708,11 @@ private Constructor getConstructor0(Class[] parameterTypes, int which) throws NoSuchMethodException { - Constructor[] constructors = privateGetDeclaredConstructors((which == Member.PUBLIC)); - for (int i = 0; i < constructors.length; i++) { + Constructor[] constructors = privateGetDeclaredConstructors((which == Member.PUBLIC)); + for (Constructor constructor : constructors) { if (arrayContentsEq(parameterTypes, - constructors[i].getParameterTypes())) { - return getReflectionFactory().copyConstructor(constructors[i]); + constructor.getParameterTypes())) { + return getReflectionFactory().copyConstructor(constructor); } } throw new NoSuchMethodException(getName() + "." + argumentTypesToString(parameterTypes)); @@ -2767,18 +2762,18 @@ return out; } - private static Constructor[] copyConstructors(Constructor[] arg) { - Constructor[] out = new Constructor[arg.length]; + private static Constructor[] copyConstructors(Constructor[] arg) { + Constructor[] out = arg.clone(); ReflectionFactory fact = getReflectionFactory(); - for (int i = 0; i < arg.length; i++) { - out[i] = fact.copyConstructor(arg[i]); + for (int i = 0; i < out.length; i++) { + out[i] = fact.copyConstructor(out[i]); } return out; } private native Field[] getDeclaredFields0(boolean publicOnly); private native Method[] getDeclaredMethods0(boolean publicOnly); - private native Constructor[] getDeclaredConstructors0(boolean publicOnly); + private native Constructor[] getDeclaredConstructors0(boolean publicOnly); private native Class[] getDeclaredClasses0(); private static String argumentTypesToString(Class[] argTypes) { @@ -2883,7 +2878,7 @@ // Fetches the factory for reflective objects private static ReflectionFactory getReflectionFactory() { if (reflectionFactory == null) { - reflectionFactory = (ReflectionFactory) + reflectionFactory = java.security.AccessController.doPrivileged (new sun.reflect.ReflectionFactory.GetReflectionFactoryAction()); } @@ -2895,8 +2890,8 @@ private static boolean initted = false; private static void checkInitted() { if (initted) return; - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { // Tests to ensure the system properties table is fully // initialized. This is needed because reflection code is // called very early in the initialization process (before @@ -2941,17 +2936,17 @@ /** * Returns the elements of this enum class or null if this * Class object does not represent an enum type; - * identical to getEnumConstantsShared except that - * the result is uncloned, cached, and shared by all callers. + * identical to getEnumConstants except that the result is + * uncloned, cached, and shared by all callers. */ T[] getEnumConstantsShared() { if (enumConstants == null) { if (!isEnum()) return null; try { final Method values = getMethod("values"); - java.security.AccessController.doPrivileged - (new java.security.PrivilegedAction() { - public Object run() { + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { values.setAccessible(true); return null; } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/lang/ClassLoader.java --- a/jdk/src/share/classes/java/lang/ClassLoader.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/lang/ClassLoader.java Tue Mar 11 23:37:02 2008 -0700 @@ -39,6 +39,7 @@ import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.security.ProtectionDomain; +import java.security.cert.Certificate; import java.util.Enumeration; import java.util.Hashtable; import java.util.HashMap; @@ -172,17 +173,18 @@ private ClassLoader parent; // Hashtable that maps packages to certs - private Hashtable package2certs = new Hashtable(11); + private Hashtable package2certs + = new Hashtable(11); // Shared among all packages with unsigned classes - java.security.cert.Certificate[] nocerts; + Certificate[] nocerts; // The classes loaded by this class loader. The only purpose of this table // is to keep the classes from being GC'ed until the loader is GC'ed. - private Vector classes = new Vector(); + private Vector> classes = new Vector>(); // The initiating protection domains for all classes loaded by this loader - private Set domains = new HashSet(); + private Set domains = new HashSet(); // Invoked by the VM to record every loaded class with this loader. void addClass(Class c) { @@ -191,7 +193,7 @@ // The packages defined in this class loader. Each package name is mapped // to its corresponding Package object. - private HashMap packages = new HashMap(); + private HashMap packages = new HashMap(); /** * Creates a new class loader using the specified parent class loader for @@ -342,8 +344,8 @@ final String name = cls.getName(); final int i = name.lastIndexOf('.'); if (i != -1) { - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { sm.checkPackageAccess(name.substring(0, i)); return null; } @@ -524,17 +526,20 @@ // Class format error - try to transform the bytecode and // define the class again // - Object[] transformers = ClassFileTransformer.getTransformers(); + ClassFileTransformer[] transformers = ClassFileTransformer.getTransformers(); Class c = null; - for (int i = 0; transformers != null && i < transformers.length; i++) { - try { - // Transform byte code using transformer - byte[] tb = ((ClassFileTransformer) transformers[i]).transform(b, off, len); - c = defineClass1(name, tb, 0, tb.length, protectionDomain, source); - break; - } catch (ClassFormatError cfe2) { - // If ClassFormatError occurs, try next transformer + if (transformers != null) { + for (ClassFileTransformer transformer : transformers) { + try { + // Transform byte code using transformer + byte[] tb = transformer.transform(b, off, len); + c = defineClass1(name, tb, 0, tb.length, + protectionDomain, source); + break; + } catch (ClassFormatError cfe2) { + // If ClassFormatError occurs, try next transformer + } } } @@ -550,7 +555,7 @@ private void postDefineClass(Class c, ProtectionDomain protectionDomain) { if (protectionDomain.getCodeSource() != null) { - java.security.cert.Certificate certs[] = + Certificate certs[] = protectionDomain.getCodeSource().getCertificates(); if (certs != null) setSigners(c, certs); @@ -767,8 +772,7 @@ private synchronized void checkCerts(String name, CodeSource cs) { int i = name.lastIndexOf('.'); String pname = (i == -1) ? "" : name.substring(0, i); - java.security.cert.Certificate[] pcerts = - (java.security.cert.Certificate[]) package2certs.get(pname); + Certificate[] pcerts = package2certs.get(pname); if (pcerts == null) { // first class in this package gets to define which // certificates must be the same for all other classes @@ -778,12 +782,12 @@ } if (pcerts == null) { if (nocerts == null) - nocerts = new java.security.cert.Certificate[0]; + nocerts = new Certificate[0]; pcerts = nocerts; } package2certs.put(pname, pcerts); } else { - java.security.cert.Certificate[] certs = null; + Certificate[] certs = null; if (cs != null) { certs = cs.getCertificates(); } @@ -799,8 +803,8 @@ * check to make sure the certs for the new class (certs) are the same as * the certs for the first class inserted in the package (pcerts) */ - private boolean compareCerts(java.security.cert.Certificate[] pcerts, - java.security.cert.Certificate[] certs) + private boolean compareCerts(Certificate[] pcerts, + Certificate[] certs) { // certs can be null, indicating no certs. if ((certs == null) || (certs.length == 0)) { @@ -1031,7 +1035,7 @@ } tmp[1] = findResources(name); - return new CompoundEnumeration(tmp); + return new CompoundEnumeration(tmp); } /** @@ -1068,7 +1072,7 @@ * @since 1.2 */ protected Enumeration findResources(String name) throws IOException { - return new CompoundEnumeration(new Enumeration[0]); + return java.util.Collections.emptyEnumeration(); } /** @@ -1134,13 +1138,13 @@ /** * Find resources from the VM's built-in classloader. */ - private static Enumeration getBootstrapResources(String name) + private static Enumeration getBootstrapResources(String name) throws IOException { - final Enumeration e = getBootstrapClassPath().getResources(name); - return new Enumeration () { - public Object nextElement() { - return ((Resource)e.nextElement()).getURL(); + final Enumeration e = getBootstrapClassPath().getResources(name); + return new Enumeration () { + public URL nextElement() { + return e.nextElement().getURL(); } public boolean hasMoreElements() { return e.hasMoreElements(); @@ -1323,9 +1327,8 @@ Throwable oops = null; scl = l.getClassLoader(); try { - PrivilegedExceptionAction a; - a = new SystemClassLoaderAction(scl); - scl = (ClassLoader) AccessController.doPrivileged(a); + scl = AccessController.doPrivileged( + new SystemClassLoaderAction(scl)); } catch (PrivilegedActionException pae) { oops = pae.getCause(); if (oops instanceof InvocationTargetException) { @@ -1456,7 +1459,7 @@ */ protected Package getPackage(String name) { synchronized (packages) { - Package pkg = (Package)packages.get(name); + Package pkg = packages.get(name); if (pkg == null) { if (parent != null) { pkg = parent.getPackage(name); @@ -1481,9 +1484,9 @@ * @since 1.2 */ protected Package[] getPackages() { - Map map; + Map map; synchronized (packages) { - map = (Map)packages.clone(); + map = new HashMap(packages); } Package[] pkgs; if (parent != null) { @@ -1499,7 +1502,7 @@ } } } - return (Package[])map.values().toArray(new Package[map.size()]); + return map.values().toArray(new Package[map.size()]); } @@ -1585,8 +1588,7 @@ // Invoked in the VM to determine the context class in // JNI_Load/JNI_Unload static Class getFromClass() { - return ((NativeLibrary) - (ClassLoader.nativeLibraryContext.peek())).fromClass; + return ClassLoader.nativeLibraryContext.peek().fromClass; } } @@ -1597,22 +1599,27 @@ // Returns (and initializes) the default domain. private synchronized ProtectionDomain getDefaultDomain() { if (defaultDomain == null) { - CodeSource cs = - new CodeSource(null, (java.security.cert.Certificate[]) null); + CodeSource cs = new CodeSource(null, (Certificate[]) null); defaultDomain = new ProtectionDomain(cs, null, this, null); } return defaultDomain; } // All native library names we've loaded. - private static Vector loadedLibraryNames = new Vector(); + private static Vector loadedLibraryNames + = new Vector(); + // Native libraries belonging to system classes. - private static Vector systemNativeLibraries = new Vector(); + private static Vector systemNativeLibraries + = new Vector(); + // Native libraries associated with the class loader. - private Vector nativeLibraries = new Vector(); + private Vector nativeLibraries + = new Vector(); // native libraries being loaded/unloaded. - private static Stack nativeLibraryContext = new Stack(); + private static Stack nativeLibraryContext + = new Stack(); // The paths searched for libraries static private String usr_paths[]; @@ -1699,13 +1706,13 @@ } private static boolean loadLibrary0(Class fromClass, final File file) { - Boolean exists = (Boolean) - AccessController.doPrivileged(new PrivilegedAction() { + boolean exists = AccessController.doPrivileged( + new PrivilegedAction() { public Object run() { - return new Boolean(file.exists()); - } - }); - if (!exists.booleanValue()) { + return file.exists() ? Boolean.TRUE : null; + }}) + != null; + if (!exists) { return false; } String name; @@ -1716,12 +1723,12 @@ } ClassLoader loader = (fromClass == null) ? null : fromClass.getClassLoader(); - Vector libs = + Vector libs = loader != null ? loader.nativeLibraries : systemNativeLibraries; synchronized (libs) { int size = libs.size(); for (int i = 0; i < size; i++) { - NativeLibrary lib = (NativeLibrary)libs.elementAt(i); + NativeLibrary lib = libs.elementAt(i); if (name.equals(lib.name)) { return true; } @@ -1748,8 +1755,7 @@ */ int n = nativeLibraryContext.size(); for (int i = 0; i < n; i++) { - NativeLibrary lib = (NativeLibrary) - nativeLibraryContext.elementAt(i); + NativeLibrary lib = nativeLibraryContext.elementAt(i); if (name.equals(lib.name)) { if (loader == lib.fromClass.getClassLoader()) { return true; @@ -1780,12 +1786,12 @@ // Invoked in the VM class linking code. static long findNative(ClassLoader loader, String name) { - Vector libs = + Vector libs = loader != null ? loader.nativeLibraries : systemNativeLibraries; synchronized (libs) { int size = libs.size(); for (int i = 0; i < size; i++) { - NativeLibrary lib = (NativeLibrary)libs.elementAt(i); + NativeLibrary lib = libs.elementAt(i); long entry = lib.find(name); if (entry != 0) return entry; @@ -1805,13 +1811,13 @@ // is null then we are delegating assertion status queries to the VM, i.e., // none of this ClassLoader's assertion status modification methods have // been invoked. - private Map packageAssertionStatus = null; + private Map packageAssertionStatus = null; // Maps String fullyQualifiedClassName to Boolean assertionStatus If this // field is null then we are delegating assertion status queries to the VM, // i.e., none of this ClassLoader's assertion status modification methods // have been invoked. - Map classAssertionStatus = null; + Map classAssertionStatus = null; /** * Sets the default assertion status for this class loader. This setting @@ -1878,7 +1884,7 @@ if (packageAssertionStatus == null) initializeJavaAssertionMaps(); - packageAssertionStatus.put(packageName, Boolean.valueOf(enabled)); + packageAssertionStatus.put(packageName, enabled); } /** @@ -1909,7 +1915,7 @@ if (classAssertionStatus == null) initializeJavaAssertionMaps(); - classAssertionStatus.put(className, Boolean.valueOf(enabled)); + classAssertionStatus.put(className, enabled); } /** @@ -1927,8 +1933,8 @@ * Whether or not "Java assertion maps" are initialized, set * them to empty maps, effectively ignoring any present settings. */ - classAssertionStatus = new HashMap(); - packageAssertionStatus = new HashMap(); + classAssertionStatus = new HashMap(); + packageAssertionStatus = new HashMap(); defaultAssertionStatus = false; } @@ -1962,20 +1968,20 @@ // assert packageAssertionStatus != null; // Check for a class entry - result = (Boolean)classAssertionStatus.get(className); + result = classAssertionStatus.get(className); if (result != null) return result.booleanValue(); // Check for most specific package entry int dotIndex = className.lastIndexOf("."); if (dotIndex < 0) { // default package - result = (Boolean)packageAssertionStatus.get(null); + result = packageAssertionStatus.get(null); if (result != null) return result.booleanValue(); } while(dotIndex > 0) { className = className.substring(0, dotIndex); - result = (Boolean)packageAssertionStatus.get(className); + result = packageAssertionStatus.get(className); if (result != null) return result.booleanValue(); dotIndex = className.lastIndexOf(".", dotIndex-1); @@ -1989,17 +1995,17 @@ private void initializeJavaAssertionMaps() { // assert Thread.holdsLock(this); - classAssertionStatus = new HashMap(); - packageAssertionStatus = new HashMap(); + classAssertionStatus = new HashMap(); + packageAssertionStatus = new HashMap(); AssertionStatusDirectives directives = retrieveDirectives(); for(int i = 0; i < directives.classes.length; i++) classAssertionStatus.put(directives.classes[i], - Boolean.valueOf(directives.classEnabled[i])); + directives.classEnabled[i]); for(int i = 0; i < directives.packages.length; i++) packageAssertionStatus.put(directives.packages[i], - Boolean.valueOf(directives.packageEnabled[i])); + directives.packageEnabled[i]); defaultAssertionStatus = directives.deflt; } @@ -2009,28 +2015,24 @@ } -class SystemClassLoaderAction implements PrivilegedExceptionAction { +class SystemClassLoaderAction + implements PrivilegedExceptionAction { private ClassLoader parent; SystemClassLoaderAction(ClassLoader parent) { this.parent = parent; } - public Object run() throws Exception { - ClassLoader sys; - Constructor ctor; - Class c; - Class cp[] = { ClassLoader.class }; - Object params[] = { parent }; - + public ClassLoader run() throws Exception { String cls = System.getProperty("java.system.class.loader"); if (cls == null) { return parent; } - c = Class.forName(cls, true, parent); - ctor = c.getDeclaredConstructor(cp); - sys = (ClassLoader) ctor.newInstance(params); + Constructor ctor = Class.forName(cls, true, parent) + .getDeclaredConstructor(new Class[] { ClassLoader.class }); + ClassLoader sys = (ClassLoader) ctor.newInstance( + new Object[] { parent }); Thread.currentThread().setContextClassLoader(sys); return sys; } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/lang/Compiler.java --- a/jdk/src/share/classes/java/lang/Compiler.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/lang/Compiler.java Tue Mar 11 23:37:02 2008 -0700 @@ -53,9 +53,9 @@ static { registerNatives(); - java.security.AccessController.doPrivileged - (new java.security.PrivilegedAction() { - public Object run() { + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { boolean loaded = false; String jit = System.getProperty("java.compiler"); if ((jit != null) && (!jit.equals("NONE")) && diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/lang/Long.java --- a/jdk/src/share/classes/java/lang/Long.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/lang/Long.java Tue Mar 11 23:37:02 2008 -0700 @@ -650,7 +650,7 @@ try { result = Long.valueOf(nm.substring(index), radix); - result = negative ? new Long((long)-result.longValue()) : result; + result = negative ? new Long(-result.longValue()) : result; } catch (NumberFormatException e) { // If number is Long.MIN_VALUE, we'll end up here. The next line // handles this case, and causes any genuine format error to be diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/lang/Package.java --- a/jdk/src/share/classes/java/lang/Package.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/lang/Package.java Tue Mar 11 23:37:02 2008 -0700 @@ -507,7 +507,7 @@ */ static Package getSystemPackage(String name) { synchronized (pkgs) { - Package pkg = (Package)pkgs.get(name); + Package pkg = pkgs.get(name); if (pkg == null) { name = name.replace('.', '/').concat("/"); String fn = getSystemPackage0(name); @@ -529,18 +529,18 @@ for (int i = 0; i < names.length; i++) { defineSystemPackage(names[i], getSystemPackage0(names[i])); } - return (Package[])pkgs.values().toArray(new Package[pkgs.size()]); + return pkgs.values().toArray(new Package[pkgs.size()]); } } private static Package defineSystemPackage(final String iname, final String fn) { - return (Package) AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + return AccessController.doPrivileged(new PrivilegedAction() { + public Package run() { String name = iname; // Get the cached code source url for the file name - URL url = (URL)urls.get(fn); + URL url = urls.get(fn); if (url == null) { // URL not found, so create one File file = new File(fn); @@ -559,7 +559,7 @@ // Convert to "."-separated package name name = name.substring(0, name.length() - 1).replace('/', '.'); Package pkg; - Manifest man = (Manifest)mans.get(fn); + Manifest man = mans.get(fn); if (man != null) { pkg = new Package(name, man, url, null); } else { @@ -588,13 +588,16 @@ } // The map of loaded system packages - private static Map pkgs = new HashMap(31); + private static Map pkgs + = new HashMap(31); // Maps each directory or zip file name to its corresponding url - private static Map urls = new HashMap(10); + private static Map urls + = new HashMap(10); // Maps each code source url for a jar file to its manifest - private static Map mans = new HashMap(10); + private static Map mans + = new HashMap(10); private static native String getSystemPackage0(String name); private static native String[] getSystemPackages0(); diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/lang/Process.java --- a/jdk/src/share/classes/java/lang/Process.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/lang/Process.java Tue Mar 11 23:37:02 2008 -0700 @@ -41,18 +41,24 @@ *

The methods that create processes may not work well for special * processes on certain native platforms, such as native windowing * processes, daemon processes, Win16/DOS processes on Microsoft - * Windows, or shell scripts. The created subprocess does not have - * its own terminal or console. All its standard I/O (i.e. stdin, - * stdout, stderr) operations will be redirected to the parent process - * through three streams - * ({@link #getOutputStream()}, - * {@link #getInputStream()}, - * {@link #getErrorStream()}). + * Windows, or shell scripts. + * + *

By default, the created subprocess does not have its own terminal + * or console. All its standard I/O (i.e. stdin, stdout, stderr) + * operations will be redirected to the parent process, where they can + * be accessed via the streams obtained using the methods + * {@link #getOutputStream()}, + * {@link #getInputStream()}, and + * {@link #getErrorStream()}. * The parent process uses these streams to feed input to and get output * from the subprocess. Because some native platforms only provide * limited buffer size for standard input and output streams, failure * to promptly write the input stream or read the output stream of - * the subprocess may cause the subprocess to block, and even deadlock. + * the subprocess may cause the subprocess to block, or even deadlock. + * + *

Where desired, + * subprocess I/O can also be redirected + * using methods of the {@link ProcessBuilder} class. * *

The subprocess is not killed when there are no more references to * the {@code Process} object, but rather the subprocess @@ -62,16 +68,22 @@ * Process} object execute asynchronously or concurrently with respect * to the Java process that owns the {@code Process} object. * - * @author unascribed - * @see ProcessBuilder + *

As of 1.5, {@link ProcessBuilder#start()} is the preferred way + * to create a {@code Process}. + * * @since JDK1.0 */ public abstract class Process { /** * Returns the output stream connected to the normal input of the * subprocess. Output to the stream is piped into the standard - * input stream of the process represented by this {@code Process} - * object. + * input of the process represented by this {@code Process} object. + * + *

If the standard input of the subprocess has been redirected using + * {@link ProcessBuilder#redirectInput(Redirect) + * ProcessBuilder.redirectInput} + * then this method will return a + * null output stream. * *

Implementation note: It is a good idea for the returned * output stream to be buffered. @@ -84,30 +96,47 @@ /** * Returns the input stream connected to the normal output of the * subprocess. The stream obtains data piped from the standard - * output stream of the process represented by this {@code - * Process} object. + * output of the process represented by this {@code Process} object. + * + *

If the standard output of the subprocess has been redirected using + * {@link ProcessBuilder#redirectOutput(Redirect) + * ProcessBuilder.redirectOutput} + * then this method will return a + * null input stream. + * + *

Otherwise, if the standard error of the subprocess has been + * redirected using + * {@link ProcessBuilder#redirectErrorStream(boolean) + * ProcessBuilder.redirectErrorStream} + * then the input stream returned by this method will receive the + * merged standard output and the standard error of the subprocess. * *

Implementation note: It is a good idea for the returned * input stream to be buffered. * * @return the input stream connected to the normal output of the * subprocess - * @see ProcessBuilder#redirectErrorStream() */ abstract public InputStream getInputStream(); /** - * Returns the input stream connected to the error output stream of - * the subprocess. The stream obtains data piped from the error - * output stream of the process represented by this {@code Process} - * object. + * Returns the input stream connected to the error output of the + * subprocess. The stream obtains data piped from the error output + * of the process represented by this {@code Process} object. + * + *

If the standard error of the subprocess has been redirected using + * {@link ProcessBuilder#redirectError(Redirect) + * ProcessBuilder.redirectError} or + * {@link ProcessBuilder#redirectErrorStream(boolean) + * ProcessBuilder.redirectErrorStream} + * then this method will return a + * null input stream. * *

Implementation note: It is a good idea for the returned * input stream to be buffered. * - * @return the input stream connected to the error output stream of + * @return the input stream connected to the error output of * the subprocess - * @see ProcessBuilder#redirectErrorStream() */ abstract public InputStream getErrorStream(); diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/lang/ProcessBuilder.java --- a/jdk/src/share/classes/java/lang/ProcessBuilder.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/lang/ProcessBuilder.java Tue Mar 11 23:37:02 2008 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,10 @@ import java.io.File; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.FileOutputStream; +import java.util.Arrays; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -34,7 +38,7 @@ /** * This class is used to create operating system processes. * - *

Each ProcessBuilder instance manages a collection + *

Each {@code ProcessBuilder} instance manages a collection * of process attributes. The {@link #start()} method creates a new * {@link Process} instance with those attributes. The {@link * #start()} method can be invoked repeatedly from the same instance @@ -59,19 +63,64 @@ * *

  • a working directory. The default value is the current * working directory of the current process, usually the directory - * named by the system property user.dir. + * named by the system property {@code user.dir}. + * + *
  • a source of standard input. + * By default, the subprocess reads input from a pipe. Java code + * can access this pipe via the output stream returned by + * {@link Process#getOutputStream()}. However, standard input may + * be redirected to another source using + * {@link #redirectInput(Redirect) redirectInput}. + * In this case, {@link Process#getOutputStream()} will return a + * null output stream, for which: + * + *
      + *
    • the {@link OutputStream#write(int) write} methods always + * throw {@code IOException} + *
    • the {@link OutputStream#close() close} method does nothing + *
    + * + *
  • a destination for standard output + * and standard error. By default, the subprocess writes standard + * output and standard error to pipes. Java code can access these pipes + * via the input streams returned by {@link Process#getInputStream()} and + * {@link Process#getErrorStream()}. However, standard output and + * standard error may be redirected to other destinations using + * {@link #redirectOutput(Redirect) redirectOutput} and + * {@link #redirectError(Redirect) redirectError}. + * In this case, {@link Process#getInputStream()} and/or + * {@link Process#getErrorStream()} will return a null input + * stream, for which: + * + *
      + *
    • the {@link InputStream#read() read} methods always return + * {@code -1} + *
    • the {@link InputStream#available() available} method always returns + * {@code 0} + *
    • the {@link InputStream#close() close} method does nothing + *
    * *
  • a redirectErrorStream property. Initially, this property - * is false, meaning that the standard output and error + * is {@code false}, meaning that the standard output and error * output of a subprocess are sent to two separate streams, which can * be accessed using the {@link Process#getInputStream()} and {@link - * Process#getErrorStream()} methods. If the value is set to - * true, the standard error is merged with the standard - * output. This makes it easier to correlate error messages with the - * corresponding output. In this case, the merged data can be read - * from the stream returned by {@link Process#getInputStream()}, while - * reading from the stream returned by {@link - * Process#getErrorStream()} will get an immediate end of file. + * Process#getErrorStream()} methods. + * + *

    If the value is set to {@code true}, then: + * + *

    * * * @@ -87,34 +136,43 @@ * is invoked. * *

    Note that this class is not synchronized. - * If multiple threads access a ProcessBuilder instance + * If multiple threads access a {@code ProcessBuilder} instance * concurrently, and at least one of the threads modifies one of the * attributes structurally, it must be synchronized externally. * *

    Starting a new process which uses the default working directory * and environment is easy: * - *

    + * 
     {@code
      * Process p = new ProcessBuilder("myCommand", "myArg").start();
    - * 
    + * } * *

    Here is an example that starts a process with a modified working - * directory and environment: + * directory and environment, and redirects standard output and error + * to be appended to a log file: * - *

    - * ProcessBuilder pb = new ProcessBuilder("myCommand", "myArg1", "myArg2");
    - * Map<String, String> env = pb.environment();
    + * 
     {@code
    + * ProcessBuilder pb =
    + *   new ProcessBuilder("myCommand", "myArg1", "myArg2");
    + * Map env = pb.environment();
      * env.put("VAR1", "myValue");
      * env.remove("OTHERVAR");
      * env.put("VAR2", env.get("VAR1") + "suffix");
      * pb.directory(new File("myDir"));
    + * File log = new File("log");
    + * pb.redirectErrorStream(true);
    + * pb.redirectOutput(Redirect.appendTo(log));
      * Process p = pb.start();
    - * 
    + * assert pb.redirectInput() == Redirect.PIPE; + * assert pb.redirectOutput().file() == log; + * assert p.getInputStream().read() == -1; + * } * *

    To start a process with an explicit set of environment * variables, first call {@link java.util.Map#clear() Map.clear()} * before adding environment variables. * + * @author Martin Buchholz * @since 1.5 */ @@ -124,20 +182,19 @@ private File directory; private Map environment; private boolean redirectErrorStream; + private Redirect[] redirects; /** * Constructs a process builder with the specified operating * system program and arguments. This constructor does not - * make a copy of the command list. Subsequent + * make a copy of the {@code command} list. Subsequent * updates to the list will be reflected in the state of the * process builder. It is not checked whether - * command corresponds to a valid operating system - * command.

    + * {@code command} corresponds to a valid operating system + * command. * - * @param command The list containing the program and its arguments - * - * @throws NullPointerException - * If the argument is null + * @param command the list containing the program and its arguments + * @throws NullPointerException if the argument is null */ public ProcessBuilder(List command) { if (command == null) @@ -149,12 +206,12 @@ * Constructs a process builder with the specified operating * system program and arguments. This is a convenience * constructor that sets the process builder's command to a string - * list containing the same strings as the command + * list containing the same strings as the {@code command} * array, in the same order. It is not checked whether - * command corresponds to a valid operating system - * command.

    + * {@code command} corresponds to a valid operating system + * command. * - * @param command A string array containing the program and its arguments + * @param command a string array containing the program and its arguments */ public ProcessBuilder(String... command) { this.command = new ArrayList(command.length); @@ -165,16 +222,15 @@ /** * Sets this process builder's operating system program and * arguments. This method does not make a copy of the - * command list. Subsequent updates to the list will + * {@code command} list. Subsequent updates to the list will * be reflected in the state of the process builder. It is not - * checked whether command corresponds to a valid - * operating system command.

    + * checked whether {@code command} corresponds to a valid + * operating system command. * - * @param command The list containing the program and its arguments - * @return This process builder + * @param command the list containing the program and its arguments + * @return this process builder * - * @throws NullPointerException - * If the argument is null + * @throws NullPointerException if the argument is null */ public ProcessBuilder command(List command) { if (command == null) @@ -187,12 +243,12 @@ * Sets this process builder's operating system program and * arguments. This is a convenience method that sets the command * to a string list containing the same strings as the - * command array, in the same order. It is not - * checked whether command corresponds to a valid - * operating system command.

    + * {@code command} array, in the same order. It is not + * checked whether {@code command} corresponds to a valid + * operating system command. * - * @param command A string array containing the program and its arguments - * @return This process builder + * @param command a string array containing the program and its arguments + * @return this process builder */ public ProcessBuilder command(String... command) { this.command = new ArrayList(command.length); @@ -205,9 +261,9 @@ * Returns this process builder's operating system program and * arguments. The returned list is not a copy. Subsequent * updates to the list will be reflected in the state of this - * process builder.

    + * process builder. * - * @return This process builder's program and its arguments + * @return this process builder's program and its arguments */ public List command() { return command; @@ -225,10 +281,10 @@ *

    The returned object may be modified using ordinary {@link * java.util.Map Map} operations. These modifications will be * visible to subprocesses started via the {@link #start()} - * method. Two ProcessBuilder instances always + * method. Two {@code ProcessBuilder} instances always * contain independent process environments, so changes to the * returned map will never be reflected in any other - * ProcessBuilder instance or the values returned by + * {@code ProcessBuilder} instance or the values returned by * {@link System#getenv System.getenv}. * *

    If the system does not support environment variables, an @@ -262,25 +318,24 @@ *

    The returned map is typically case-sensitive on all platforms. * *

    If a security manager exists, its - * {@link SecurityManager#checkPermission checkPermission} - * method is called with a - * {@link RuntimePermission}("getenv.*") - * permission. This may result in a {@link SecurityException} being - * thrown. + * {@link SecurityManager#checkPermission checkPermission} method + * is called with a + * {@link RuntimePermission}{@code ("getenv.*")} permission. + * This may result in a {@link SecurityException} being thrown. * *

    When passing information to a Java subprocess, * system properties - * are generally preferred over environment variables.

    + * are generally preferred over environment variables. * - * @return This process builder's environment + * @return this process builder's environment * - * @throws SecurityException - * If a security manager exists and its - * {@link SecurityManager#checkPermission checkPermission} - * method doesn't allow access to the process environment + * @throws SecurityException + * if a security manager exists and its + * {@link SecurityManager#checkPermission checkPermission} + * method doesn't allow access to the process environment * - * @see Runtime#exec(String[],String[],java.io.File) - * @see System#getenv() + * @see Runtime#exec(String[],String[],java.io.File) + * @see System#getenv() */ public Map environment() { SecurityManager security = System.getSecurityManager(); @@ -328,12 +383,12 @@ * * Subprocesses subsequently started by this object's {@link * #start()} method will use this as their working directory. - * The returned value may be null -- this means to use + * The returned value may be {@code null} -- this means to use * the working directory of the current Java process, usually the - * directory named by the system property user.dir, - * as the working directory of the child process.

    + * directory named by the system property {@code user.dir}, + * as the working directory of the child process. * - * @return This process builder's working directory + * @return this process builder's working directory */ public File directory() { return directory; @@ -344,50 +399,522 @@ * * Subprocesses subsequently started by this object's {@link * #start()} method will use this as their working directory. - * The argument may be null -- this means to use the + * The argument may be {@code null} -- this means to use the * working directory of the current Java process, usually the - * directory named by the system property user.dir, - * as the working directory of the child process.

    + * directory named by the system property {@code user.dir}, + * as the working directory of the child process. * - * @param directory The new working directory - * @return This process builder + * @param directory the new working directory + * @return this process builder */ public ProcessBuilder directory(File directory) { this.directory = directory; return this; } + // ---------------- I/O Redirection ---------------- + + /** + * Implements a null input stream. + */ + static class NullInputStream extends InputStream { + public int read() { return -1; } + public int available() { return 0; } + } + + /** + * Implements a null output stream. + */ + static class NullOutputStream extends OutputStream { + public void write(int b) throws IOException { + throw new IOException("Stream closed"); + } + } + + /** + * Represents a source of subprocess input or a destination of + * subprocess output. + * + * Each {@code Redirect} instance is one of the following: + * + *
      + *
    • the special value {@link #PIPE Redirect.PIPE} + *
    • the special value {@link #INHERIT Redirect.INHERIT} + *
    • a redirection to read from a file, created by an invocation of + * {@link Redirect#from Redirect.from(File)} + *
    • a redirection to write to a file, created by an invocation of + * {@link Redirect#to Redirect.to(File)} + *
    • a redirection to append to a file, created by an invocation of + * {@link Redirect#appendTo Redirect.appendTo(File)} + *
    + * + *

    Each of the above categories has an associated unique + * {@link Type Type}. + * + * @since 1.7 + */ + public static abstract class Redirect { + /** + * The type of a {@link Redirect}. + */ + public enum Type { + /** + * The type of {@link Redirect#PIPE Redirect.PIPE}. + */ + PIPE, + + /** + * The type of {@link Redirect#INHERIT Redirect.INHERIT}. + */ + INHERIT, + + /** + * The type of redirects returned from + * {@link Redirect#from Redirect.from(File)}. + */ + READ, + + /** + * The type of redirects returned from + * {@link Redirect#to Redirect.to(File)}. + */ + WRITE, + + /** + * The type of redirects returned from + * {@link Redirect#appendTo Redirect.appendTo(File)}. + */ + APPEND + }; + + /** + * Returns the type of this {@code Redirect}. + * @return the type of this {@code Redirect} + */ + public abstract Type type(); + + /** + * Indicates that subprocess I/O will be connected to the + * current Java process over a pipe. + * + * This is the default handling of subprocess standard I/O. + * + *

    It will always be true that + *

     {@code
    +         * Redirect.PIPE.file() == null &&
    +         * Redirect.PIPE.type() == Redirect.Type.PIPE
    +         * }
    + */ + public static final Redirect PIPE = new Redirect() { + public Type type() { return Type.PIPE; } + public String toString() { return type().toString(); }}; + + /** + * Indicates that subprocess I/O source or destination will be the + * same as those of the current process. This is the normal + * behavior of most operating system command interpreters (shells). + * + *

    It will always be true that + *

     {@code
    +         * Redirect.INHERIT.file() == null &&
    +         * Redirect.INHERIT.type() == Redirect.Type.INHERIT
    +         * }
    + */ + public static final Redirect INHERIT = new Redirect() { + public Type type() { return Type.INHERIT; } + public String toString() { return type().toString(); }}; + + /** + * Returns the {@link File} source or destination associated + * with this redirect, or {@code null} if there is no such file. + * + * @return the file associated with this redirect, + * or {@code null} if there is no such file + */ + public File file() { return null; } + + FileOutputStream toFileOutputStream() throws IOException { + throw new UnsupportedOperationException(); + } + + /** + * Returns a redirect to read from the specified file. + * + *

    It will always be true that + *

     {@code
    +         * Redirect.from(file).file() == file &&
    +         * Redirect.from(file).type() == Redirect.Type.READ
    +         * }
    + * + * @throws NullPointerException if the specified file is null + * @return a redirect to read from the specified file + */ + public static Redirect from(final File file) { + if (file == null) + throw new NullPointerException(); + return new Redirect() { + public Type type() { return Type.READ; } + public File file() { return file; } + public String toString() { + return "redirect to read from file \"" + file + "\""; + } + }; + } + + /** + * Returns a redirect to write to the specified file. + * If the specified file exists when the subprocess is started, + * its previous contents will be discarded. + * + *

    It will always be true that + *

     {@code
    +         * Redirect.to(file).file() == file &&
    +         * Redirect.to(file).type() == Redirect.Type.WRITE
    +         * }
    + * + * @throws NullPointerException if the specified file is null + * @return a redirect to write to the specified file + */ + public static Redirect to(final File file) { + if (file == null) + throw new NullPointerException(); + return new Redirect() { + public Type type() { return Type.WRITE; } + public File file() { return file; } + public String toString() { + return "redirect to write to file \"" + file + "\""; + } + FileOutputStream toFileOutputStream() throws IOException { + return new FileOutputStream(file, false); + } + }; + } + + /** + * Returns a redirect to append to the specified file. + * Each write operation first advances the position to the + * end of the file and then writes the requested data. + * Whether the advancement of the position and the writing + * of the data are done in a single atomic operation is + * system-dependent and therefore unspecified. + * + *

    It will always be true that + *

     {@code
    +         * Redirect.appendTo(file).file() == file &&
    +         * Redirect.appendTo(file).type() == Redirect.Type.APPEND
    +         * }
    + * + * @throws NullPointerException if the specified file is null + * @return a redirect to append to the specified file + */ + public static Redirect appendTo(final File file) { + if (file == null) + throw new NullPointerException(); + return new Redirect() { + public Type type() { return Type.APPEND; } + public File file() { return file; } + public String toString() { + return "redirect to append to file \"" + file + "\""; + } + FileOutputStream toFileOutputStream() throws IOException { + return new FileOutputStream(file, true); + } + }; + } + + /** + * Compares the specified object with this {@code Redirect} for + * equality. Returns {@code true} if and only if the two + * objects are identical or both objects are {@code Redirect} + * instances of the same type associated with non-null equal + * {@code File} instances. + */ + public boolean equals(Object obj) { + if (obj == this) + return true; + if (! (obj instanceof Redirect)) + return false; + Redirect r = (Redirect) obj; + if (r.type() != this.type()) + return false; + assert this.file() != null; + return this.file().equals(r.file()); + } + + /** + * Returns a hash code value for this {@code Redirect}. + * @return a hash code value for this {@code Redirect} + */ + public int hashCode() { + File file = file(); + if (file == null) + return super.hashCode(); + else + return file.hashCode(); + } + + /** + * No public constructors. Clients must use predefined + * static {@code Redirect} instances or factory methods. + */ + private Redirect() {} + } + + private Redirect[] redirects() { + if (redirects == null) + redirects = new Redirect[] { + Redirect.PIPE, Redirect.PIPE, Redirect.PIPE + }; + return redirects; + } + + /** + * Sets this process builder's standard input source. + * + * Subprocesses subsequently started by this object's {@link #start()} + * method obtain their standard input from this source. + * + *

    If the source is {@link Redirect#PIPE Redirect.PIPE} + * (the initial value), then the standard input of a + * subprocess can be written to using the output stream + * returned by {@link Process#getOutputStream()}. + * If the source is set to any other value, then + * {@link Process#getOutputStream()} will return a + * null output stream. + * + * @param source the new standard input source + * @return this process builder + * @throws IllegalArgumentException + * if the redirect does not correspond to a valid source + * of data, that is, has type + * {@link Redirect.Type#WRITE WRITE} or + * {@link Redirect.Type#APPEND APPEND} + * @since 1.7 + */ + public ProcessBuilder redirectInput(Redirect source) { + if (source.type() == Redirect.Type.WRITE || + source.type() == Redirect.Type.APPEND) + throw new IllegalArgumentException( + "Redirect invalid for reading: " + source); + redirects()[0] = source; + return this; + } + + /** + * Sets this process builder's standard output destination. + * + * Subprocesses subsequently started by this object's {@link #start()} + * method send their standard output to this destination. + * + *

    If the destination is {@link Redirect#PIPE Redirect.PIPE} + * (the initial value), then the standard output of a subprocess + * can be read using the input stream returned by {@link + * Process#getInputStream()}. + * If the destination is set to any other value, then + * {@link Process#getInputStream()} will return a + * null input stream. + * + * @param destination the new standard output destination + * @return this process builder + * @throws IllegalArgumentException + * if the redirect does not correspond to a valid + * destination of data, that is, has type + * {@link Redirect.Type#READ READ} + * @since 1.7 + */ + public ProcessBuilder redirectOutput(Redirect destination) { + if (destination.type() == Redirect.Type.READ) + throw new IllegalArgumentException( + "Redirect invalid for writing: " + destination); + redirects()[1] = destination; + return this; + } + + /** + * Sets this process builder's standard error destination. + * + * Subprocesses subsequently started by this object's {@link #start()} + * method send their standard error to this destination. + * + *

    If the destination is {@link Redirect#PIPE Redirect.PIPE} + * (the initial value), then the error output of a subprocess + * can be read using the input stream returned by {@link + * Process#getErrorStream()}. + * If the destination is set to any other value, then + * {@link Process#getErrorStream()} will return a + * null input stream. + * + *

    If the {@link #redirectErrorStream redirectErrorStream} + * attribute has been set {@code true}, then the redirection set + * by this method has no effect. + * + * @param destination the new standard error destination + * @return this process builder + * @throws IllegalArgumentException + * if the redirect does not correspond to a valid + * destination of data, that is, has type + * {@link Redirect.Type#READ READ} + * @since 1.7 + */ + public ProcessBuilder redirectError(Redirect destination) { + if (destination.type() == Redirect.Type.READ) + throw new IllegalArgumentException( + "Redirect invalid for writing: " + destination); + redirects()[2] = destination; + return this; + } + + /** + * Sets this process builder's standard input source to a file. + * + *

    This is a convenience method. An invocation of the form + * {@code redirectInput(file)} + * behaves in exactly the same way as the invocation + * {@link #redirectInput(Redirect) redirectInput} + * {@code (Redirect.from(file))}. + * + * @param file the new standard input source + * @return this process builder + * @since 1.7 + */ + public ProcessBuilder redirectInput(File file) { + return redirectInput(Redirect.from(file)); + } + + /** + * Sets this process builder's standard output destination to a file. + * + *

    This is a convenience method. An invocation of the form + * {@code redirectOutput(file)} + * behaves in exactly the same way as the invocation + * {@link #redirectOutput(Redirect) redirectOutput} + * {@code (Redirect.to(file))}. + * + * @param file the new standard output destination + * @return this process builder + * @since 1.7 + */ + public ProcessBuilder redirectOutput(File file) { + return redirectOutput(Redirect.to(file)); + } + + /** + * Sets this process builder's standard error destination to a file. + * + *

    This is a convenience method. An invocation of the form + * {@code redirectError(file)} + * behaves in exactly the same way as the invocation + * {@link #redirectError(Redirect) redirectError} + * {@code (Redirect.to(file))}. + * + * @param file the new standard error destination + * @return this process builder + * @since 1.7 + */ + public ProcessBuilder redirectError(File file) { + return redirectError(Redirect.to(file)); + } + + /** + * Returns this process builder's standard input source. + * + * Subprocesses subsequently started by this object's {@link #start()} + * method obtain their standard input from this source. + * The initial value is {@link Redirect#PIPE Redirect.PIPE}. + * + * @return this process builder's standard input source + * @since 1.7 + */ + public Redirect redirectInput() { + return (redirects == null) ? Redirect.PIPE : redirects[0]; + } + + /** + * Returns this process builder's standard output destination. + * + * Subprocesses subsequently started by this object's {@link #start()} + * method redirect their standard output to this destination. + * The initial value is {@link Redirect#PIPE Redirect.PIPE}. + * + * @return this process builder's standard output destination + * @since 1.7 + */ + public Redirect redirectOutput() { + return (redirects == null) ? Redirect.PIPE : redirects[1]; + } + + /** + * Returns this process builder's standard error destination. + * + * Subprocesses subsequently started by this object's {@link #start()} + * method redirect their standard error to this destination. + * The initial value is {@link Redirect#PIPE Redirect.PIPE}. + * + * @return this process builder's standard error destination + * @since 1.7 + */ + public Redirect redirectError() { + return (redirects == null) ? Redirect.PIPE : redirects[2]; + } + + /** + * Sets the source and destination for subprocess standard I/O + * to be the same as those of the current Java process. + * + *

    This is a convenience method. An invocation of the form + *

     {@code
    +     * pb.inheritIO()
    +     * }
    + * behaves in exactly the same way as the invocation + *
     {@code
    +     * pb.redirectInput(Redirect.INHERIT)
    +     *   .redirectOutput(Redirect.INHERIT)
    +     *   .redirectError(Redirect.INHERIT)
    +     * }
    + * + * This gives behavior equivalent to most operating system + * command interpreters, or the standard C library function + * {@code system()}. + * + * @return this process builder + * @since 1.7 + */ + public ProcessBuilder inheritIO() { + Arrays.fill(redirects(), Redirect.INHERIT); + return this; + } + /** * Tells whether this process builder merges standard error and * standard output. * - *

    If this property is true, then any error output + *

    If this property is {@code true}, then any error output * generated by subprocesses subsequently started by this object's * {@link #start()} method will be merged with the standard * output, so that both can be read using the * {@link Process#getInputStream()} method. This makes it easier * to correlate error messages with the corresponding output. - * The initial value is false.

    + * The initial value is {@code false}. * - * @return This process builder's redirectErrorStream property + * @return this process builder's {@code redirectErrorStream} property */ public boolean redirectErrorStream() { return redirectErrorStream; } /** - * Sets this process builder's redirectErrorStream property. + * Sets this process builder's {@code redirectErrorStream} property. * - *

    If this property is true, then any error output + *

    If this property is {@code true}, then any error output * generated by subprocesses subsequently started by this object's * {@link #start()} method will be merged with the standard * output, so that both can be read using the * {@link Process#getInputStream()} method. This makes it easier * to correlate error messages with the corresponding output. - * The initial value is false.

    + * The initial value is {@code false}. * - * @param redirectErrorStream The new property value - * @return This process builder + * @param redirectErrorStream the new property value + * @return this process builder */ public ProcessBuilder redirectErrorStream(boolean redirectErrorStream) { this.redirectErrorStream = redirectErrorStream; @@ -410,7 +937,7 @@ *

    If there is a security manager, its * {@link SecurityManager#checkExec checkExec} * method is called with the first component of this object's - * command array as its argument. This may result in + * {@code command} array as its argument. This may result in * a {@link SecurityException} being thrown. * *

    Starting an operating system process is highly system-dependent. @@ -426,26 +953,42 @@ * subclass of {@link IOException}. * *

    Subsequent modifications to this process builder will not - * affect the returned {@link Process}.

    + * affect the returned {@link Process}. * - * @return A new {@link Process} object for managing the subprocess + * @return a new {@link Process} object for managing the subprocess + * + * @throws NullPointerException + * if an element of the command list is null * - * @throws NullPointerException - * If an element of the command list is null + * @throws IndexOutOfBoundsException + * if the command is an empty list (has size {@code 0}) * - * @throws IndexOutOfBoundsException - * If the command is an empty list (has size 0) + * @throws SecurityException + * if a security manager exists and + *
      + * + *
    • its + * {@link SecurityManager#checkExec checkExec} + * method doesn't allow creation of the subprocess, or * - * @throws SecurityException - * If a security manager exists and its - * {@link SecurityManager#checkExec checkExec} - * method doesn't allow creation of the subprocess + *
    • the standard input to the subprocess was + * {@linkplain #redirectInput redirected from a file} + * and the security manager's + * {@link SecurityManager#checkRead checkRead} method + * denies read access to the file, or * - * @throws IOException - * If an I/O error occurs + *
    • the standard output or standard error of the + * subprocess was + * {@linkplain #redirectOutput redirected to a file} + * and the security manager's + * {@link SecurityManager#checkWrite checkWrite} method + * denies write access to the file * - * @see Runtime#exec(String[], String[], java.io.File) - * @see SecurityManager#checkExec(String) + *
    + * + * @throws IOException if an I/O error occurs + * + * @see Runtime#exec(String[], String[], java.io.File) */ public Process start() throws IOException { // Must convert to array first -- a malicious user-supplied @@ -467,6 +1010,7 @@ return ProcessImpl.start(cmdarray, environment, dir, + redirects, redirectErrorStream); } catch (IOException e) { // It's much easier for us to create a high-quality error diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/lang/StringCoding.java --- a/jdk/src/share/classes/java/lang/StringCoding.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/lang/StringCoding.java Tue Mar 11 23:37:02 2008 -0700 @@ -53,22 +53,23 @@ private StringCoding() { } - /* The cached coders for each thread - */ - private static ThreadLocal decoder = new ThreadLocal(); - private static ThreadLocal encoder = new ThreadLocal(); + /** The cached coders for each thread */ + private final static ThreadLocal> decoder = + new ThreadLocal>(); + private final static ThreadLocal> encoder = + new ThreadLocal>(); private static boolean warnUnsupportedCharset = true; - private static Object deref(ThreadLocal tl) { - SoftReference sr = (SoftReference)tl.get(); + private static T deref(ThreadLocal> tl) { + SoftReference sr = tl.get(); if (sr == null) return null; return sr.get(); } - private static void set(ThreadLocal tl, Object ob) { - tl.set(new SoftReference(ob)); + private static void set(ThreadLocal> tl, T ob) { + tl.set(new SoftReference(ob)); } // Trim the given byte array to the given length @@ -174,7 +175,7 @@ static char[] decode(String charsetName, byte[] ba, int off, int len) throws UnsupportedEncodingException { - StringDecoder sd = (StringDecoder)deref(decoder); + StringDecoder sd = deref(decoder); String csn = (charsetName == null) ? "ISO-8859-1" : charsetName; if ((sd == null) || !(csn.equals(sd.requestedCharsetName()) || csn.equals(sd.charsetName()))) { @@ -193,8 +194,7 @@ static char[] decode(Charset cs, byte[] ba, int off, int len) { StringDecoder sd = new StringDecoder(cs, cs.name()); - byte[] b = Arrays.copyOf(ba, ba.length); - return sd.decode(b, off, len); + return sd.decode(Arrays.copyOfRange(ba, off, off + len), 0, len); } static char[] decode(byte[] ba, int off, int len) { @@ -273,7 +273,7 @@ static byte[] encode(String charsetName, char[] ca, int off, int len) throws UnsupportedEncodingException { - StringEncoder se = (StringEncoder)deref(encoder); + StringEncoder se = deref(encoder); String csn = (charsetName == null) ? "ISO-8859-1" : charsetName; if ((se == null) || !(csn.equals(se.requestedCharsetName()) || csn.equals(se.charsetName()))) { @@ -292,8 +292,7 @@ static byte[] encode(Charset cs, char[] ca, int off, int len) { StringEncoder se = new StringEncoder(cs, cs.name()); - char[] c = Arrays.copyOf(ca, ca.length); - return se.encode(c, off, len); + return se.encode(Arrays.copyOfRange(ca, off, off + len), 0, len); } static byte[] encode(char[] ca, int off, int len) { diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/lang/ref/Finalizer.java --- a/jdk/src/share/classes/java/lang/ref/Finalizer.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/lang/ref/Finalizer.java Tue Mar 11 23:37:02 2008 -0700 @@ -121,8 +121,9 @@ invokers of these methods from a stalled or deadlocked finalizer thread. */ private static void forkSecondaryFinalizer(final Runnable proc) { - PrivilegedAction pa = new PrivilegedAction() { - public Object run() { + AccessController.doPrivileged( + new PrivilegedAction() { + public Void run() { ThreadGroup tg = Thread.currentThread().getThreadGroup(); for (ThreadGroup tgn = tg; tgn != null; @@ -135,8 +136,7 @@ /* Ignore */ } return null; - }}; - AccessController.doPrivileged(pa); + }}); } /* Called by Runtime.runFinalization() */ diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/lang/reflect/AccessibleObject.java --- a/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java Tue Mar 11 23:37:02 2008 -0700 @@ -165,9 +165,9 @@ // Reflection factory used by subclasses for creating field, // method, and constructor accessors. Note that this is called // very early in the bootstrapping process. - static final ReflectionFactory reflectionFactory = (ReflectionFactory) - AccessController.doPrivileged - (new sun.reflect.ReflectionFactory.GetReflectionFactoryAction()); + static final ReflectionFactory reflectionFactory = + AccessController.doPrivileged( + new sun.reflect.ReflectionFactory.GetReflectionFactoryAction()); /** * @throws NullPointerException {@inheritDoc} diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/lang/reflect/Modifier.java --- a/jdk/src/share/classes/java/lang/reflect/Modifier.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/lang/reflect/Modifier.java Tue Mar 11 23:37:02 2008 -0700 @@ -58,9 +58,8 @@ */ static { sun.reflect.ReflectionFactory factory = - (sun.reflect.ReflectionFactory) AccessController.doPrivileged( - new ReflectionFactory.GetReflectionFactoryAction() - ); + AccessController.doPrivileged( + new ReflectionFactory.GetReflectionFactoryAction()); factory.setLangReflectAccess(new java.lang.reflect.ReflectAccess()); } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/lang/reflect/Proxy.java --- a/jdk/src/share/classes/java/lang/reflect/Proxy.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/lang/reflect/Proxy.java Tue Mar 11 23:37:02 2008 -0700 @@ -33,6 +33,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.List; import java.util.WeakHashMap; import sun.misc.ProxyGenerator; @@ -230,7 +231,8 @@ { InvocationHandler.class }; /** maps a class loader to the proxy class cache for that loader */ - private static Map loaderToCache = new WeakHashMap(); + private static Map, Object>> loaderToCache + = new WeakHashMap, Object>>(); /** marks that a particular proxy class is currently being generated */ private static Object pendingGenerationMarker = new Object(); @@ -240,8 +242,8 @@ private static Object nextUniqueNumberLock = new Object(); /** set of all generated proxy classes, for isProxyClass implementation */ - private static Map proxyClasses = - Collections.synchronizedMap(new WeakHashMap()); + private static Map, Void> proxyClasses = + Collections.synchronizedMap(new WeakHashMap, Void>()); /** * the invocation handler for this proxy instance. @@ -353,7 +355,8 @@ /* collect interface names to use as key for proxy class cache */ String[] interfaceNames = new String[interfaces.length]; - Set interfaceSet = new HashSet(); // for detecting duplicates + // for detecting duplicates + Set> interfaceSet = new HashSet>(); for (int i = 0; i < interfaces.length; i++) { /* @@ -401,16 +404,16 @@ * representation of a class makes for an implicit weak * reference to the class. */ - Object key = Arrays.asList(interfaceNames); + List key = Arrays.asList(interfaceNames); /* * Find or create the proxy class cache for the class loader. */ - Map cache; + Map, Object> cache; synchronized (loaderToCache) { - cache = (Map) loaderToCache.get(loader); + cache = loaderToCache.get(loader); if (cache == null) { - cache = new HashMap(); + cache = new HashMap, Object>(); loaderToCache.put(loader, cache); } /* @@ -442,7 +445,7 @@ do { Object value = cache.get(key); if (value instanceof Reference) { - proxyClass = (Class) ((Reference) value).get(); + proxyClass = (Class) ((Reference) value).get(); } if (proxyClass != null) { // proxy class already generated: return it @@ -544,7 +547,7 @@ */ synchronized (cache) { if (proxyClass != null) { - cache.put(key, new WeakReference(proxyClass)); + cache.put(key, new WeakReference>(proxyClass)); } else { cache.remove(key); } @@ -595,14 +598,14 @@ /* * Look up or generate the designated proxy class. */ - Class cl = getProxyClass(loader, interfaces); + Class cl = getProxyClass(loader, interfaces); /* * Invoke its constructor with the designated invocation handler. */ try { Constructor cons = cl.getConstructor(constructorParams); - return (Object) cons.newInstance(new Object[] { h }); + return cons.newInstance(new Object[] { h }); } catch (NoSuchMethodException e) { throw new InternalError(e.toString()); } catch (IllegalAccessException e) { diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/net/DatagramSocket.java --- a/jdk/src/share/classes/java/net/DatagramSocket.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/net/DatagramSocket.java Tue Mar 11 23:37:02 2008 -0700 @@ -287,8 +287,9 @@ // DatagramSocketImpl.peekdata() is a protected method, therefore we need to use // getDeclaredMethod, therefore we need permission to access the member try { - AccessController.doPrivileged(new PrivilegedExceptionAction() { - public Object run() throws NoSuchMethodException { + AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public Void run() throws NoSuchMethodException { Class[] cl = new Class[1]; cl[0] = DatagramPacket.class; impl.getClass().getDeclaredMethod("peekData", cl); diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/net/ServerSocket.java --- a/jdk/src/share/classes/java/net/ServerSocket.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/net/ServerSocket.java Tue Mar 11 23:37:02 2008 -0700 @@ -247,8 +247,9 @@ // SocketImpl.connect() is a protected method, therefore we need to use // getDeclaredMethod, therefore we need permission to access the member try { - AccessController.doPrivileged(new PrivilegedExceptionAction() { - public Object run() throws NoSuchMethodException { + AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public Void run() throws NoSuchMethodException { Class[] cl = new Class[2]; cl[0] = SocketAddress.class; cl[1] = Integer.TYPE; diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/net/Socket.java --- a/jdk/src/share/classes/java/net/Socket.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/net/Socket.java Tue Mar 11 23:37:02 2008 -0700 @@ -731,6 +731,7 @@ * then this method will continue to return the connected address * after the socket is closed. * + * @return a SocketAddress representing the remote endpoint of this * socket, or null if it is not connected yet. * @see #getInetAddress() @@ -847,9 +848,9 @@ final Socket s = this; InputStream is = null; try { - is = (InputStream) - AccessController.doPrivileged(new PrivilegedExceptionAction() { - public Object run() throws IOException { + is = AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public InputStream run() throws IOException { return impl.getInputStream(); } }); @@ -887,9 +888,9 @@ final Socket s = this; OutputStream os = null; try { - os = (OutputStream) - AccessController.doPrivileged(new PrivilegedExceptionAction() { - public Object run() throws IOException { + os = AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public OutputStream run() throws IOException { return impl.getOutputStream(); } }); diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/net/SocksSocketImpl.java --- a/jdk/src/share/classes/java/net/SocksSocketImpl.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/net/SocksSocketImpl.java Tue Mar 11 23:37:02 2008 -0700 @@ -78,8 +78,8 @@ { try { AccessController.doPrivileged( - new java.security.PrivilegedExceptionAction() { - public Object run() throws IOException { + new java.security.PrivilegedExceptionAction() { + public Void run() throws IOException { superConnectServer(host, port, timeout); cmdIn = getInputStream(); cmdOut = getOutputStream(); @@ -129,10 +129,10 @@ String userName; String password = null; final InetAddress addr = InetAddress.getByName(server); - PasswordAuthentication pw = (PasswordAuthentication) + PasswordAuthentication pw = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { + new java.security.PrivilegedAction() { + public PasswordAuthentication run() { return Authenticator.requestPasswordAuthentication( server, addr, port, "SOCKS5", "SOCKS authentication", null); } @@ -339,10 +339,9 @@ // This is the general case // server is not null only when the socket was created with a // specified proxy in which case it does bypass the ProxySelector - ProxySelector sel = (ProxySelector) - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { + ProxySelector sel = java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public ProxySelector run() { return ProxySelector.getDefault(); } }); @@ -652,10 +651,9 @@ // This is the general case // server is not null only when the socket was created with a // specified proxy in which case it does bypass the ProxySelector - ProxySelector sel = (ProxySelector) - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { + ProxySelector sel = java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public ProxySelector run() { return ProxySelector.getDefault(); } }); @@ -701,8 +699,9 @@ // Connects to the SOCKS server try { - AccessController.doPrivileged(new PrivilegedExceptionAction() { - public Object run() throws Exception { + AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public Void run() throws Exception { cmdsock = new Socket(new PlainSocketImpl()); cmdsock.connect(new InetSocketAddress(server, port)); cmdIn = cmdsock.getInputStream(); @@ -731,8 +730,9 @@ } } else { try { - AccessController.doPrivileged(new PrivilegedExceptionAction() { - public Object run() throws Exception { + AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public Void run() throws Exception { cmdsock = new Socket(new PlainSocketImpl()); cmdsock.connect(new InetSocketAddress(server, port)); cmdIn = cmdsock.getInputStream(); diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/net/URLClassLoader.java --- a/jdk/src/share/classes/java/net/URLClassLoader.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/net/URLClassLoader.java Tue Mar 11 23:37:02 2008 -0700 @@ -205,9 +205,9 @@ throws ClassNotFoundException { try { - return (Class) - AccessController.doPrivileged(new PrivilegedExceptionAction() { - public Object run() throws ClassNotFoundException { + return AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public Class run() throws ClassNotFoundException { String path = name.replace('.', '/').concat(".class"); Resource res = ucp.getResource(path, false); if (res != null) { @@ -376,9 +376,9 @@ /* * The same restriction to finding classes applies to resources */ - URL url = - (URL) AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + URL url = AccessController.doPrivileged( + new PrivilegedAction() { + public URL run() { return ucp.findResource(name, true); } }, acc); @@ -397,7 +397,7 @@ public Enumeration findResources(final String name) throws IOException { - final Enumeration e = ucp.findResources(name, true); + final Enumeration e = ucp.findResources(name, true); return new Enumeration() { private URL url = null; @@ -407,9 +407,9 @@ return true; } do { - URL u = (URL) - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + URL u = AccessController.doPrivileged( + new PrivilegedAction() { + public URL run() { if (!e.hasMoreElements()) return null; return e.nextElement(); @@ -515,8 +515,8 @@ final SecurityManager sm = System.getSecurityManager(); if (sm != null) { final Permission fp = p; - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() throws SecurityException { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() throws SecurityException { sm.checkPermission(fp); return null; } @@ -544,9 +544,9 @@ // Save the caller's context AccessControlContext acc = AccessController.getContext(); // Need a privileged block to create the class loader - URLClassLoader ucl = - (URLClassLoader) AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + URLClassLoader ucl = AccessController.doPrivileged( + new PrivilegedAction() { + public URLClassLoader run() { return new FactoryURLClassLoader(urls, parent); } }); @@ -571,9 +571,9 @@ // Save the caller's context AccessControlContext acc = AccessController.getContext(); // Need a privileged block to create the class loader - URLClassLoader ucl = (URLClassLoader) - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + URLClassLoader ucl = AccessController.doPrivileged( + new PrivilegedAction() { + public URLClassLoader run() { return new FactoryURLClassLoader(urls); } }); diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/nio/channels/Channels.java --- a/jdk/src/share/classes/java/nio/channels/Channels.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/nio/channels/Channels.java Tue Mar 11 23:37:02 2008 -0700 @@ -66,7 +66,27 @@ private Channels() { } // No instantiation - private static int write(WritableByteChannel ch, ByteBuffer bb) + /** + * Write all remaining bytes in buffer to the given channel. + * If the channel is selectable then it must be configured blocking. + */ + private static void writeFullyImpl(WritableByteChannel ch, ByteBuffer bb) + throws IOException + { + while (bb.remaining() > 0) { + int n = ch.write(bb); + if (n <= 0) + throw new RuntimeException("no bytes written"); + } + } + + /** + * Write all remaining bytes in buffer to the given channel. + * + * @throws IllegalBlockingException + * If the channel is selectable and configured non-blocking. + */ + private static void writeFully(WritableByteChannel ch, ByteBuffer bb) throws IOException { if (ch instanceof SelectableChannel) { @@ -74,14 +94,13 @@ synchronized (sc.blockingLock()) { if (!sc.isBlocking()) throw new IllegalBlockingModeException(); - return ch.write(bb); + writeFullyImpl(ch, bb); } } else { - return ch.write(bb); + writeFullyImpl(ch, bb); } } - // -- Byte streams from channels -- /** @@ -148,7 +167,7 @@ bb.position(off); this.bb = bb; this.bs = bs; - Channels.write(ch, bb); + Channels.writeFully(ch, bb); } public void close() throws IOException { diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/nio/channels/spi/SelectorProvider.java --- a/jdk/src/share/classes/java/nio/channels/spi/SelectorProvider.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/nio/channels/spi/SelectorProvider.java Tue Mar 11 23:37:02 2008 -0700 @@ -167,9 +167,9 @@ synchronized (lock) { if (provider != null) return provider; - return (SelectorProvider)AccessController - .doPrivileged(new PrivilegedAction() { - public Object run() { + return AccessController.doPrivileged( + new PrivilegedAction() { + public SelectorProvider run() { if (loadProviderFromProperty()) return provider; if (loadProviderAsService()) diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/nio/charset/Charset.java --- a/jdk/src/share/classes/java/nio/charset/Charset.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/nio/charset/Charset.java Tue Mar 11 23:37:02 2008 -0700 @@ -212,36 +212,47 @@ * *

    Terminology

    * - *

    The name of this class is taken from the terms used in RFC 2278. In that - * document a charset is defined as the combination of a coded character - * set and a character-encoding scheme. + *

    The name of this class is taken from the terms used in + * RFC 2278. + * In that document a charset is defined as the combination of + * one or more coded character sets and a character-encoding scheme. + * (This definition is confusing; some other software systems define + * charset as a synonym for coded character set.) * *

    A coded character set is a mapping between a set of abstract * characters and a set of integers. US-ASCII, ISO 8859-1, - * JIS X 0201, and full Unicode, which is the same as - * ISO 10646-1, are examples of coded character sets. + * JIS X 0201, and Unicode are examples of coded character sets. + * + *

    Some standards have defined a character set to be simply a + * set of abstract characters without an associated assigned numbering. + * An alphabet is an example of such a character set. However, the subtle + * distinction between character set and coded character set + * is rarely used in practice; the former has become a short form for the + * latter, including in the Java API specification. * - *

    A character-encoding scheme is a mapping between a coded - * character set and a set of octet (eight-bit byte) sequences. UTF-8, UCS-2, - * UTF-16, ISO 2022, and EUC are examples of character-encoding schemes. - * Encoding schemes are often associated with a particular coded character set; - * UTF-8, for example, is used only to encode Unicode. Some schemes, however, - * are associated with multiple character sets; EUC, for example, can be used - * to encode characters in a variety of Asian character sets. + *

    A character-encoding scheme is a mapping between one or more + * coded character sets and a set of octet (eight-bit byte) sequences. + * UTF-8, UTF-16, ISO 2022, and EUC are examples of + * character-encoding schemes. Encoding schemes are often associated with + * a particular coded character set; UTF-8, for example, is used only to + * encode Unicode. Some schemes, however, are associated with multiple + * coded character sets; EUC, for example, can be used to encode + * characters in a variety of Asian coded character sets. * *

    When a coded character set is used exclusively with a single - * character-encoding scheme then the corresponding charset is usually named - * for the character set; otherwise a charset is usually named for the encoding - * scheme and, possibly, the locale of the character sets that it supports. - * Hence US-ASCII is the name of the charset for US-ASCII while + * character-encoding scheme then the corresponding charset is usually + * named for the coded character set; otherwise a charset is usually named + * for the encoding scheme and, possibly, the locale of the coded + * character sets that it supports. Hence US-ASCII is both the + * name of a coded character set and of the charset that encodes it, while * EUC-JP is the name of the charset that encodes the * JIS X 0201, JIS X 0208, and JIS X 0212 - * character sets. + * coded character sets for the Japanese language. * *

    The native character encoding of the Java programming language is - * UTF-16. A charset in the Java platform therefore defines a mapping between - * sequences of sixteen-bit UTF-16 code units and sequences of bytes.

    + * UTF-16. A charset in the Java platform therefore defines a mapping + * between sequences of sixteen-bit UTF-16 code units (that is, sequences + * of chars) and sequences of bytes.

    * * * @author Mark Reinhold diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/rmi/activation/ActivationGroupDesc.java --- a/jdk/src/share/classes/java/rmi/activation/ActivationGroupDesc.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/rmi/activation/ActivationGroupDesc.java Tue Mar 11 23:37:02 2008 -0700 @@ -263,7 +263,7 @@ * @since 1.2 */ public String[] getCommandOptions() { - return (String[]) options.clone(); + return options.clone(); } /** diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/rmi/dgc/VMID.java --- a/jdk/src/share/classes/java/rmi/dgc/VMID.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/rmi/dgc/VMID.java Tue Mar 11 23:37:02 2008 -0700 @@ -136,9 +136,9 @@ /* * Get the local host's IP address. */ - byte[] addr = (byte[]) java.security.AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { + byte[] addr = java.security.AccessController.doPrivileged( + new PrivilegedAction() { + public byte[] run() { try { return InetAddress.getLocalHost().getAddress(); } catch (Exception e) { diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/security/cert/TrustAnchor.java --- a/jdk/src/share/classes/java/security/cert/TrustAnchor.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/security/cert/TrustAnchor.java Tue Mar 11 23:37:02 2008 -0700 @@ -275,7 +275,7 @@ ncBytes = null; nc = null; } else { - ncBytes = (byte []) bytes.clone(); + ncBytes = bytes.clone(); // validate DER encoding try { nc = new NameConstraintsExtension(Boolean.FALSE, bytes); @@ -309,7 +309,7 @@ * or null if not set. */ public final byte [] getNameConstraints() { - return (ncBytes == null ? null : (byte []) ncBytes.clone()); + return ncBytes == null ? null : ncBytes.clone(); } /** diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/security/cert/X509CertSelector.java --- a/jdk/src/share/classes/java/security/cert/X509CertSelector.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/security/cert/X509CertSelector.java Tue Mar 11 23:37:02 2008 -0700 @@ -381,7 +381,7 @@ if (subjectKeyID == null) { this.subjectKeyID = null; } else { - this.subjectKeyID = (byte[])subjectKeyID.clone(); + this.subjectKeyID = subjectKeyID.clone(); } } @@ -442,7 +442,7 @@ if (authorityKeyID == null) { this.authorityKeyID = null; } else { - this.authorityKeyID = (byte[])authorityKeyID.clone(); + this.authorityKeyID = authorityKeyID.clone(); } } @@ -566,7 +566,7 @@ subjectPublicKey = null; subjectPublicKeyBytes = null; } else { - subjectPublicKeyBytes = (byte[])key.clone(); + subjectPublicKeyBytes = key.clone(); subjectPublicKey = X509Key.parse(new DerValue(subjectPublicKeyBytes)); } } @@ -590,7 +590,7 @@ if (keyUsage == null) { this.keyUsage = null; } else { - this.keyUsage = (boolean[])keyUsage.clone(); + this.keyUsage = keyUsage.clone(); } } @@ -1041,7 +1041,7 @@ ncBytes = null; nc = null; } else { - ncBytes = (byte[])bytes.clone(); + ncBytes = bytes.clone(); nc = new NameConstraintsExtension(FALSE, bytes); } } @@ -1438,7 +1438,7 @@ if (subjectKeyID == null) { return null; } - return (byte[])subjectKeyID.clone(); + return subjectKeyID.clone(); } /** @@ -1457,7 +1457,7 @@ if (authorityKeyID == null) { return null; } - return (byte[])authorityKeyID.clone(); + return authorityKeyID.clone(); } /** @@ -1546,7 +1546,7 @@ if (keyUsage == null) { return null; } - return (boolean[])keyUsage.clone(); + return keyUsage.clone(); } /** @@ -1736,7 +1736,7 @@ if (ncBytes == null) { return null; } else { - return (byte[]) ncBytes.clone(); + return ncBytes.clone(); } } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/util/ArrayList.java --- a/jdk/src/share/classes/java/util/ArrayList.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/util/ArrayList.java Tue Mar 11 23:37:02 2008 -0700 @@ -892,7 +892,7 @@ private final AbstractList parent; private final int parentOffset; private final int offset; - private int size; + int size; SubList(AbstractList parent, int offset, int fromIndex, int toIndex) { @@ -971,6 +971,7 @@ public ListIterator listIterator(final int index) { checkForComodification(); rangeCheckForAdd(index); + final int offset = this.offset; return new ListIterator() { int cursor = index; diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/util/Arrays.java --- a/jdk/src/share/classes/java/util/Arrays.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/util/Arrays.java Tue Mar 11 23:37:02 2008 -0700 @@ -1088,7 +1088,7 @@ * mutually comparable (for example, strings and integers). */ public static void sort(Object[] a) { - Object[] aux = (Object[])a.clone(); + Object[] aux = a.clone(); mergeSort(aux, a, 0, a.length, 0); } @@ -1216,7 +1216,7 @@ * not mutually comparable using the specified comparator. */ public static void sort(T[] a, Comparator c) { - T[] aux = (T[])a.clone(); + T[] aux = a.clone(); if (c==null) mergeSort(aux, a, 0, a.length, 0); else @@ -1257,7 +1257,7 @@ public static void sort(T[] a, int fromIndex, int toIndex, Comparator c) { rangeCheck(a.length, fromIndex, toIndex); - T[] aux = (T[])copyOfRange(a, fromIndex, toIndex); + T[] aux = copyOfRange(a, fromIndex, toIndex); if (c==null) mergeSort(aux, a, fromIndex, toIndex, -fromIndex); else @@ -4128,7 +4128,7 @@ if (a.length != 0 && bufLen <= 0) bufLen = Integer.MAX_VALUE; StringBuilder buf = new StringBuilder(bufLen); - deepToString(a, buf, new HashSet()); + deepToString(a, buf, new HashSet()); return buf.toString(); } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/util/EnumMap.java --- a/jdk/src/share/classes/java/util/EnumMap.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/util/EnumMap.java Tue Mar 11 23:37:02 2008 -0700 @@ -140,7 +140,7 @@ public EnumMap(EnumMap m) { keyType = m.keyType; keyUniverse = m.keyUniverse; - vals = (Object[]) m.vals.clone(); + vals = m.vals.clone(); size = m.size; } @@ -161,7 +161,7 @@ EnumMap em = (EnumMap) m; keyType = em.keyType; keyUniverse = em.keyUniverse; - vals = (Object[]) em.vals.clone(); + vals = em.vals.clone(); size = em.size; } else { if (m.isEmpty()) @@ -257,7 +257,7 @@ public V put(K key, V value) { typeCheck(key); - int index = ((Enum)key).ordinal(); + int index = key.ordinal(); Object oldValue = vals[index]; vals[index] = maskNull(value); if (oldValue == null) @@ -662,7 +662,7 @@ } catch(CloneNotSupportedException e) { throw new AssertionError(); } - result.vals = (Object[]) result.vals.clone(); + result.vals = result.vals.clone(); return result; } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/util/HashMap.java --- a/jdk/src/share/classes/java/util/HashMap.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/util/HashMap.java Tue Mar 11 23:37:02 2008 -0700 @@ -173,7 +173,7 @@ * rehash). This field is used to make iterators on Collection-views of * the HashMap fail-fast. (See ConcurrentModificationException). */ - transient volatile int modCount; + transient int modCount; /** * Constructs an empty HashMap with the specified initial diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/util/Hashtable.java --- a/jdk/src/share/classes/java/util/Hashtable.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/util/Hashtable.java Tue Mar 11 23:37:02 2008 -0700 @@ -27,7 +27,7 @@ import java.io.*; /** - * This class implements a hashtable, which maps keys to values. Any + * This class implements a hash table, which maps keys to values. Any * non-null object can be used as a key or as a value.

    * * To successfully store and retrieve objects from a hashtable, the @@ -100,9 +100,15 @@ * *

    As of the Java 2 platform v1.2, this class was retrofitted to * implement the {@link Map} interface, making it a member of the - * Java - * Collections Framework. Unlike the new collection - * implementations, {@code Hashtable} is synchronized. + * + * + * Java Collections Framework. Unlike the new collection + * implementations, {@code Hashtable} is synchronized. If a + * thread-safe implementation is not needed, it is recommended to use + * {@link HashMap} in place of {@code Hashtable}. If a thread-safe + * highly-concurrent implementation is desired, then it is recommended + * to use {@link java.util.concurrent.ConcurrentHashMap} in place of + * {@code Hashtable}. * * @author Arthur van Hoff * @author Josh Bloch diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/util/IdentityHashMap.java --- a/jdk/src/share/classes/java/util/IdentityHashMap.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/util/IdentityHashMap.java Tue Mar 11 23:37:02 2008 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -173,7 +173,7 @@ /** * The number of modifications, to support fast-fail iterators */ - private transient volatile int modCount; + private transient int modCount; /** * The next size value at which to resize (capacity * load factor). @@ -701,7 +701,7 @@ try { IdentityHashMap m = (IdentityHashMap) super.clone(); m.entrySet = null; - m.table = (Object[])table.clone(); + m.table = table.clone(); return m; } catch (CloneNotSupportedException e) { throw new InternalError(); @@ -749,7 +749,6 @@ expectedModCount = ++modCount; int deletedSlot = lastReturnedIndex; lastReturnedIndex = -1; - size--; // back up index to revisit new contents after deletion index = deletedSlot; indexValid = false; @@ -782,6 +781,8 @@ return; } + size--; + Object item; for (int i = nextKeyIndex(d, len); (item = tab[i]) != null; i = nextKeyIndex(i, len)) { @@ -975,7 +976,7 @@ */ public boolean removeAll(Collection c) { boolean modified = false; - for (Iterator i = iterator(); i.hasNext(); ) { + for (Iterator i = iterator(); i.hasNext(); ) { if (c.contains(i.next())) { i.remove(); modified = true; @@ -1033,7 +1034,7 @@ return containsValue(o); } public boolean remove(Object o) { - for (Iterator i = iterator(); i.hasNext(); ) { + for (Iterator i = iterator(); i.hasNext(); ) { if (i.next() == o) { i.remove(); return true; @@ -1121,7 +1122,7 @@ */ public boolean removeAll(Collection c) { boolean modified = false; - for (Iterator i = iterator(); i.hasNext(); ) { + for (Iterator> i = iterator(); i.hasNext(); ) { if (c.contains(i.next())) { i.remove(); modified = true; diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/util/JumboEnumSet.java --- a/jdk/src/share/classes/java/util/JumboEnumSet.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/util/JumboEnumSet.java Tue Mar 11 23:37:02 2008 -0700 @@ -364,7 +364,7 @@ public EnumSet clone() { JumboEnumSet result = (JumboEnumSet) super.clone(); - result.elements = (long[]) result.elements.clone(); + result.elements = result.elements.clone(); return result; } } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/util/Random.java --- a/jdk/src/share/classes/java/util/Random.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/util/Random.java Tue Mar 11 23:37:02 2008 -0700 @@ -504,7 +504,7 @@ // The seed is read in as {@code long} for // historical reasons, but it is converted to an AtomicLong. - long seedVal = (long) fields.get("seed", -1L); + long seedVal = fields.get("seed", -1L); if (seedVal < 0) throw new java.io.StreamCorruptedException( "Random: invalid seed"); diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/util/TreeSet.java --- a/jdk/src/share/classes/java/util/TreeSet.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/util/TreeSet.java Tue Mar 11 23:37:02 2008 -0700 @@ -195,7 +195,7 @@ * @since 1.6 */ public NavigableSet descendingSet() { - return new TreeSet(m.descendingMap()); + return new TreeSet(m.descendingMap()); } /** @@ -505,8 +505,8 @@ s.writeInt(m.size()); // Write out all elements in the proper order. - for (Iterator i=m.keySet().iterator(); i.hasNext(); ) - s.writeObject(i.next()); + for (E e : m.keySet()) + s.writeObject(e); } /** diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/util/Vector.java --- a/jdk/src/share/classes/java/util/Vector.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/util/Vector.java Tue Mar 11 23:37:02 2008 -0700 @@ -64,15 +64,15 @@ * *

    As of the Java 2 platform v1.2, this class was retrofitted to * implement the {@link List} interface, making it a member of the - * Java - * Collections Framework. Unlike the new collection - * implementations, {@code Vector} is synchronized. + * + * Java Collections Framework. Unlike the new collection + * implementations, {@code Vector} is synchronized. If a thread-safe + * implementation is not needed, it is recommended to use {@link + * ArrayList} in place of {@code Vector}. * * @author Lee Boynton * @author Jonathan Payne * @see Collection - * @see List - * @see ArrayList * @see LinkedList * @since JDK1.0 */ diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/util/WeakHashMap.java --- a/jdk/src/share/classes/java/util/WeakHashMap.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/util/WeakHashMap.java Tue Mar 11 23:37:02 2008 -0700 @@ -29,7 +29,8 @@ /** - * A hashtable-based Map implementation with weak keys. + * Hash table based implementation of the Map interface, with + * weak keys. * An entry in a WeakHashMap will automatically be removed when * its key is no longer in ordinary use. More precisely, the presence of a * mapping for a given key will not prevent the key from being discarded by the @@ -181,7 +182,7 @@ * * @see ConcurrentModificationException */ - volatile int modCount; + int modCount; @SuppressWarnings("unchecked") private Entry[] newTable(int n) { diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/util/concurrent/DelayQueue.java --- a/jdk/src/share/classes/java/util/concurrent/DelayQueue.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/util/concurrent/DelayQueue.java Tue Mar 11 23:37:02 2008 -0700 @@ -69,10 +69,34 @@ implements BlockingQueue { private transient final ReentrantLock lock = new ReentrantLock(); - private transient final Condition available = lock.newCondition(); private final PriorityQueue q = new PriorityQueue(); /** + * Thread designated to wait for the element at the head of + * the queue. This variant of the Leader-Follower pattern + * (http://www.cs.wustl.edu/~schmidt/POSA/POSA2/) serves to + * minimize unnecessary timed waiting. When a thread becomes + * the leader, it waits only for the next delay to elapse, but + * other threads await indefinitely. The leader thread must + * signal some other thread before returning from take() or + * poll(...), unless some other thread becomes leader in the + * interim. Whenever the head of the queue is replaced with + * an element with an earlier expiration time, the leader + * field is invalidated by being reset to null, and some + * waiting thread, but not necessarily the current leader, is + * signalled. So waiting threads must be prepared to acquire + * and lose leadership while waiting. + */ + private Thread leader = null; + + /** + * Condition signalled when a newer element becomes available + * at the head of the queue or a new thread may need to + * become leader. + */ + private final Condition available = lock.newCondition(); + + /** * Creates a new DelayQueue that is initially empty. */ public DelayQueue() {} @@ -111,10 +135,11 @@ final ReentrantLock lock = this.lock; lock.lock(); try { - E first = q.peek(); q.offer(e); - if (first == null || e.compareTo(first) < 0) - available.signalAll(); + if (q.peek() == e) { + leader = null; + available.signal(); + } return true; } finally { lock.unlock(); @@ -160,13 +185,8 @@ E first = q.peek(); if (first == null || first.getDelay(TimeUnit.NANOSECONDS) > 0) return null; - else { - E x = q.poll(); - assert x != null; - if (q.size() != 0) - available.signalAll(); - return x; - } + else + return q.poll(); } finally { lock.unlock(); } @@ -185,23 +205,29 @@ try { for (;;) { E first = q.peek(); - if (first == null) { + if (first == null) available.await(); - } else { - long delay = first.getDelay(TimeUnit.NANOSECONDS); - if (delay > 0) { - long tl = available.awaitNanos(delay); - } else { - E x = q.poll(); - assert x != null; - if (q.size() != 0) - available.signalAll(); // wake up other takers - return x; - + else { + long delay = first.getDelay(TimeUnit.NANOSECONDS); + if (delay <= 0) + return q.poll(); + else if (leader != null) + available.await(); + else { + Thread thisThread = Thread.currentThread(); + leader = thisThread; + try { + available.awaitNanos(delay); + } finally { + if (leader == thisThread) + leader = null; + } } } } } finally { + if (leader == null && q.peek() != null) + available.signal(); lock.unlock(); } } @@ -230,23 +256,28 @@ nanos = available.awaitNanos(nanos); } else { long delay = first.getDelay(TimeUnit.NANOSECONDS); - if (delay > 0) { - if (nanos <= 0) - return null; - if (delay > nanos) - delay = nanos; - long timeLeft = available.awaitNanos(delay); - nanos -= delay - timeLeft; - } else { - E x = q.poll(); - assert x != null; - if (q.size() != 0) - available.signalAll(); - return x; + if (delay <= 0) + return q.poll(); + if (nanos <= 0) + return null; + if (nanos < delay || leader != null) + nanos = available.awaitNanos(nanos); + else { + Thread thisThread = Thread.currentThread(); + leader = thisThread; + try { + long timeLeft = available.awaitNanos(delay); + nanos -= delay - timeLeft; + } finally { + if (leader == thisThread) + leader = null; + } } } } } finally { + if (leader == null && q.peek() != null) + available.signal(); lock.unlock(); } } @@ -303,8 +334,6 @@ c.add(q.poll()); ++n; } - if (n > 0) - available.signalAll(); return n; } finally { lock.unlock(); @@ -335,8 +364,6 @@ c.add(q.poll()); ++n; } - if (n > 0) - available.signalAll(); return n; } finally { lock.unlock(); @@ -485,6 +512,7 @@ return cursor < array.length; } + @SuppressWarnings("unchecked") public E next() { if (cursor >= array.length) throw new NoSuchElementException(); diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/util/concurrent/ExecutorService.java --- a/jdk/src/share/classes/java/util/concurrent/ExecutorService.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/util/concurrent/ExecutorService.java Tue Mar 11 23:37:02 2008 -0700 @@ -145,6 +145,10 @@ * tasks are executed, but no new tasks will be accepted. * Invocation has no additional effect if already shut down. * + *

    This method does not wait for previously submitted tasks to + * complete execution. Use {@link #awaitTermination awaitTermination} + * to do that. + * * @throws SecurityException if a security manager exists and * shutting down this ExecutorService may manipulate * threads that the caller is not permitted to modify @@ -157,8 +161,12 @@ /** * Attempts to stop all actively executing tasks, halts the - * processing of waiting tasks, and returns a list of the tasks that were - * awaiting execution. + * processing of waiting tasks, and returns a list of the tasks + * that were awaiting execution. + * + *

    This method does not wait for actively executing tasks to + * terminate. Use {@link #awaitTermination awaitTermination} to + * do that. * *

    There are no guarantees beyond best-effort attempts to stop * processing actively executing tasks. For example, typical diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java --- a/jdk/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java Tue Mar 11 23:37:02 2008 -0700 @@ -35,6 +35,7 @@ package java.util.concurrent; import java.util.concurrent.atomic.*; +import java.util.concurrent.locks.*; import java.util.*; /** @@ -45,12 +46,21 @@ * flexibility or capabilities of {@link ThreadPoolExecutor} (which * this class extends) are required. * - *

    Delayed tasks execute no sooner than they are enabled, but + *

    Delayed tasks execute no sooner than they are enabled, but * without any real-time guarantees about when, after they are * enabled, they will commence. Tasks scheduled for exactly the same * execution time are enabled in first-in-first-out (FIFO) order of * submission. * + *

    When a submitted task is cancelled before it is run, execution + * is suppressed. By default, such a cancelled task is not + * automatically removed from the work queue until its delay + * elapses. While this enables further inspection and monitoring, it + * may also cause unbounded retention of cancelled tasks. To avoid + * this, set {@link #setRemoveOnCancelPolicy} to {@code true}, which + * causes tasks to be immediately removed from the work queue at + * time of cancellation. + * *

    While this class inherits from {@link ThreadPoolExecutor}, a few * of the inherited tuning methods are not useful for it. In * particular, because it acts as a fixed-sized pool using @@ -111,21 +121,11 @@ * ScheduledExecutorService methods) which are treated as * delayed tasks with a delay of zero. * - * 2. Using a custom queue (DelayedWorkQueue) based on an + * 2. Using a custom queue (DelayedWorkQueue), a variant of * unbounded DelayQueue. The lack of capacity constraint and * the fact that corePoolSize and maximumPoolSize are * effectively identical simplifies some execution mechanics - * (see delayedExecute) compared to ThreadPoolExecutor - * version. - * - * The DelayedWorkQueue class is defined below for the sake of - * ensuring that all elements are instances of - * RunnableScheduledFuture. Since DelayQueue otherwise - * requires type be Delayed, but not necessarily Runnable, and - * the workQueue requires the opposite, we need to explicitly - * define a class that requires both to ensure that users don't - * add objects that aren't RunnableScheduledFutures via - * getQueue().add() etc. + * (see delayedExecute) compared to ThreadPoolExecutor. * * 3. Supporting optional run-after-shutdown parameters, which * leads to overrides of shutdown methods to remove and cancel @@ -150,6 +150,11 @@ private volatile boolean executeExistingDelayedTasksAfterShutdown = true; /** + * True if ScheduledFutureTask.cancel should remove from queue + */ + private volatile boolean removeOnCancel = false; + + /** * Sequence number to break scheduling ties, and in turn to * guarantee FIFO order among tied entries. */ @@ -167,8 +172,10 @@ /** Sequence number to break ties FIFO */ private final long sequenceNumber; + /** The time the task is enabled to execute in nanoTime units */ private long time; + /** * Period in nanoseconds for repeating tasks. A positive * value indicates fixed-rate execution. A negative value @@ -181,6 +188,11 @@ RunnableScheduledFuture outerTask = this; /** + * Index into delay queue, to support faster cancellation. + */ + int heapIndex; + + /** * Creates a one-shot action with given nanoTime-based trigger time. */ ScheduledFutureTask(Runnable r, V result, long ns) { @@ -255,6 +267,13 @@ time = now() - p; } + public boolean cancel(boolean mayInterruptIfRunning) { + boolean cancelled = super.cancel(mayInterruptIfRunning); + if (cancelled && removeOnCancel && heapIndex >= 0) + remove(this); + return cancelled; + } + /** * Overrides FutureTask version so as to reset/requeue if periodic. */ @@ -655,14 +674,47 @@ } /** + * Sets the policy on whether cancelled tasks should be immediately + * removed from the work queue at time of cancellation. This value is + * by default {@code false}. + * + * @param value if {@code true}, remove on cancellation, else don't + * @see #getRemoveOnCancelPolicy + * @since 1.7 + */ + public void setRemoveOnCancelPolicy(boolean value) { + removeOnCancel = value; + } + + /** + * Gets the policy on whether cancelled tasks should be immediately + * removed from the work queue at time of cancellation. This value is + * by default {@code false}. + * + * @return {@code true} if cancelled tasks are immediately removed + * from the queue + * @see #setRemoveOnCancelPolicy + * @since 1.7 + */ + public boolean getRemoveOnCancelPolicy() { + return removeOnCancel; + } + + /** * Initiates an orderly shutdown in which previously submitted - * tasks are executed, but no new tasks will be accepted. If the - * {@code ExecuteExistingDelayedTasksAfterShutdownPolicy} has - * been set {@code false}, existing delayed tasks whose delays - * have not yet elapsed are cancelled. And unless the - * {@code ContinueExistingPeriodicTasksAfterShutdownPolicy} has - * been set {@code true}, future executions of existing periodic - * tasks will be cancelled. + * tasks are executed, but no new tasks will be accepted. + * Invocation has no additional effect if already shut down. + * + *

    This method does not wait for previously submitted tasks to + * complete execution. Use {@link #awaitTermination awaitTermination} + * to do that. + * + *

    If the {@code ExecuteExistingDelayedTasksAfterShutdownPolicy} + * has been set {@code false}, existing delayed tasks whose delays + * have not yet elapsed are cancelled. And unless the {@code + * ContinueExistingPeriodicTasksAfterShutdownPolicy} has been set + * {@code true}, future executions of existing periodic tasks will + * be cancelled. * * @throws SecurityException {@inheritDoc} */ @@ -675,6 +727,10 @@ * processing of waiting tasks, and returns a list of the tasks * that were awaiting execution. * + *

    This method does not wait for actively executing tasks to + * terminate. Use {@link #awaitTermination awaitTermination} to + * do that. + * *

    There are no guarantees beyond best-effort attempts to stop * processing actively executing tasks. This implementation * cancels tasks via {@link Thread#interrupt}, so any task that @@ -707,56 +763,478 @@ } /** - * An annoying wrapper class to convince javac to use a - * DelayQueue as a BlockingQueue + * Specialized delay queue. To mesh with TPE declarations, this + * class must be declared as a BlockingQueue even though + * it can only hold RunnableScheduledFutures. */ - private static class DelayedWorkQueue - extends AbstractCollection + static class DelayedWorkQueue extends AbstractQueue implements BlockingQueue { - private final DelayQueue dq = new DelayQueue(); - public Runnable poll() { return dq.poll(); } - public Runnable peek() { return dq.peek(); } - public Runnable take() throws InterruptedException { return dq.take(); } - public Runnable poll(long timeout, TimeUnit unit) throws InterruptedException { - return dq.poll(timeout, unit); + /* + * A DelayedWorkQueue is based on a heap-based data structure + * like those in DelayQueue and PriorityQueue, except that + * every ScheduledFutureTask also records its index into the + * heap array. This eliminates the need to find a task upon + * cancellation, greatly speeding up removal (down from O(n) + * to O(log n)), and reducing garbage retention that would + * otherwise occur by waiting for the element to rise to top + * before clearing. But because the queue may also hold + * RunnableScheduledFutures that are not ScheduledFutureTasks, + * we are not guaranteed to have such indices available, in + * which case we fall back to linear search. (We expect that + * most tasks will not be decorated, and that the faster cases + * will be much more common.) + * + * All heap operations must record index changes -- mainly + * within siftUp and siftDown. Upon removal, a task's + * heapIndex is set to -1. Note that ScheduledFutureTasks can + * appear at most once in the queue (this need not be true for + * other kinds of tasks or work queues), so are uniquely + * identified by heapIndex. + */ + + private static final int INITIAL_CAPACITY = 16; + private RunnableScheduledFuture[] queue = + new RunnableScheduledFuture[INITIAL_CAPACITY]; + private final ReentrantLock lock = new ReentrantLock(); + private int size = 0; + + /** + * Thread designated to wait for the task at the head of the + * queue. This variant of the Leader-Follower pattern + * (http://www.cs.wustl.edu/~schmidt/POSA/POSA2/) serves to + * minimize unnecessary timed waiting. When a thread becomes + * the leader, it waits only for the next delay to elapse, but + * other threads await indefinitely. The leader thread must + * signal some other thread before returning from take() or + * poll(...), unless some other thread becomes leader in the + * interim. Whenever the head of the queue is replaced with a + * task with an earlier expiration time, the leader field is + * invalidated by being reset to null, and some waiting + * thread, but not necessarily the current leader, is + * signalled. So waiting threads must be prepared to acquire + * and lose leadership while waiting. + */ + private Thread leader = null; + + /** + * Condition signalled when a newer task becomes available at the + * head of the queue or a new thread may need to become leader. + */ + private final Condition available = lock.newCondition(); + + /** + * Set f's heapIndex if it is a ScheduledFutureTask. + */ + private void setIndex(RunnableScheduledFuture f, int idx) { + if (f instanceof ScheduledFutureTask) + ((ScheduledFutureTask)f).heapIndex = idx; + } + + /** + * Sift element added at bottom up to its heap-ordered spot. + * Call only when holding lock. + */ + private void siftUp(int k, RunnableScheduledFuture key) { + while (k > 0) { + int parent = (k - 1) >>> 1; + RunnableScheduledFuture e = queue[parent]; + if (key.compareTo(e) >= 0) + break; + queue[k] = e; + setIndex(e, k); + k = parent; + } + queue[k] = key; + setIndex(key, k); + } + + /** + * Sift element added at top down to its heap-ordered spot. + * Call only when holding lock. + */ + private void siftDown(int k, RunnableScheduledFuture key) { + int half = size >>> 1; + while (k < half) { + int child = (k << 1) + 1; + RunnableScheduledFuture c = queue[child]; + int right = child + 1; + if (right < size && c.compareTo(queue[right]) > 0) + c = queue[child = right]; + if (key.compareTo(c) <= 0) + break; + queue[k] = c; + setIndex(c, k); + k = child; + } + queue[k] = key; + setIndex(key, k); + } + + /** + * Resize the heap array. Call only when holding lock. + */ + private void grow() { + int oldCapacity = queue.length; + int newCapacity = oldCapacity + (oldCapacity >> 1); // grow 50% + if (newCapacity < 0) // overflow + newCapacity = Integer.MAX_VALUE; + queue = Arrays.copyOf(queue, newCapacity); + } + + /** + * Find index of given object, or -1 if absent + */ + private int indexOf(Object x) { + if (x != null) { + if (x instanceof ScheduledFutureTask) { + int i = ((ScheduledFutureTask) x).heapIndex; + // Sanity check; x could conceivably be a + // ScheduledFutureTask from some other pool. + if (i >= 0 && i < size && queue[i] == x) + return i; + } else { + for (int i = 0; i < size; i++) + if (x.equals(queue[i])) + return i; + } + } + return -1; + } + + public boolean contains(Object x) { + final ReentrantLock lock = this.lock; + lock.lock(); + try { + return indexOf(x) != -1; + } finally { + lock.unlock(); + } + } + + public boolean remove(Object x) { + final ReentrantLock lock = this.lock; + lock.lock(); + try { + int i = indexOf(x); + if (i < 0) + return false; + + setIndex(queue[i], -1); + int s = --size; + RunnableScheduledFuture replacement = queue[s]; + queue[s] = null; + if (s != i) { + siftDown(i, replacement); + if (queue[i] == replacement) + siftUp(i, replacement); + } + return true; + } finally { + lock.unlock(); + } + } + + public int size() { + final ReentrantLock lock = this.lock; + lock.lock(); + try { + return size; + } finally { + lock.unlock(); + } + } + + public boolean isEmpty() { + return size() == 0; + } + + public int remainingCapacity() { + return Integer.MAX_VALUE; + } + + public RunnableScheduledFuture peek() { + final ReentrantLock lock = this.lock; + lock.lock(); + try { + return queue[0]; + } finally { + lock.unlock(); + } + } + + public boolean offer(Runnable x) { + if (x == null) + throw new NullPointerException(); + RunnableScheduledFuture e = (RunnableScheduledFuture)x; + final ReentrantLock lock = this.lock; + lock.lock(); + try { + int i = size; + if (i >= queue.length) + grow(); + size = i + 1; + if (i == 0) { + queue[0] = e; + setIndex(e, 0); + } else { + siftUp(i, e); + } + if (queue[0] == e) { + leader = null; + available.signal(); + } + } finally { + lock.unlock(); + } + return true; + } + + public void put(Runnable e) { + offer(e); + } + + public boolean add(Runnable e) { + return offer(e); } - public boolean add(Runnable x) { - return dq.add((RunnableScheduledFuture)x); + public boolean offer(Runnable e, long timeout, TimeUnit unit) { + return offer(e); } - public boolean offer(Runnable x) { - return dq.offer((RunnableScheduledFuture)x); + + /** + * Performs common bookkeeping for poll and take: Replaces + * first element with last and sifts it down. Call only when + * holding lock. + * @param f the task to remove and return + */ + private RunnableScheduledFuture finishPoll(RunnableScheduledFuture f) { + int s = --size; + RunnableScheduledFuture x = queue[s]; + queue[s] = null; + if (s != 0) + siftDown(0, x); + setIndex(f, -1); + return f; + } + + public RunnableScheduledFuture poll() { + final ReentrantLock lock = this.lock; + lock.lock(); + try { + RunnableScheduledFuture first = queue[0]; + if (first == null || first.getDelay(TimeUnit.NANOSECONDS) > 0) + return null; + else + return finishPoll(first); + } finally { + lock.unlock(); + } } - public void put(Runnable x) { - dq.put((RunnableScheduledFuture)x); + + public RunnableScheduledFuture take() throws InterruptedException { + final ReentrantLock lock = this.lock; + lock.lockInterruptibly(); + try { + for (;;) { + RunnableScheduledFuture first = queue[0]; + if (first == null) + available.await(); + else { + long delay = first.getDelay(TimeUnit.NANOSECONDS); + if (delay <= 0) + return finishPoll(first); + else if (leader != null) + available.await(); + else { + Thread thisThread = Thread.currentThread(); + leader = thisThread; + try { + available.awaitNanos(delay); + } finally { + if (leader == thisThread) + leader = null; + } + } + } + } + } finally { + if (leader == null && queue[0] != null) + available.signal(); + lock.unlock(); + } } - public boolean offer(Runnable x, long timeout, TimeUnit unit) { - return dq.offer((RunnableScheduledFuture)x, timeout, unit); + + public RunnableScheduledFuture poll(long timeout, TimeUnit unit) + throws InterruptedException { + long nanos = unit.toNanos(timeout); + final ReentrantLock lock = this.lock; + lock.lockInterruptibly(); + try { + for (;;) { + RunnableScheduledFuture first = queue[0]; + if (first == null) { + if (nanos <= 0) + return null; + else + nanos = available.awaitNanos(nanos); + } else { + long delay = first.getDelay(TimeUnit.NANOSECONDS); + if (delay <= 0) + return finishPoll(first); + if (nanos <= 0) + return null; + if (nanos < delay || leader != null) + nanos = available.awaitNanos(nanos); + else { + Thread thisThread = Thread.currentThread(); + leader = thisThread; + try { + long timeLeft = available.awaitNanos(delay); + nanos -= delay - timeLeft; + } finally { + if (leader == thisThread) + leader = null; + } + } + } + } + } finally { + if (leader == null && queue[0] != null) + available.signal(); + lock.unlock(); + } } - public Runnable remove() { return dq.remove(); } - public Runnable element() { return dq.element(); } - public void clear() { dq.clear(); } - public int drainTo(Collection c) { return dq.drainTo(c); } - public int drainTo(Collection c, int maxElements) { - return dq.drainTo(c, maxElements); + public void clear() { + final ReentrantLock lock = this.lock; + lock.lock(); + try { + for (int i = 0; i < size; i++) { + RunnableScheduledFuture t = queue[i]; + if (t != null) { + queue[i] = null; + setIndex(t, -1); + } + } + size = 0; + } finally { + lock.unlock(); + } + } + + /** + * Return and remove first element only if it is expired. + * Used only by drainTo. Call only when holding lock. + */ + private RunnableScheduledFuture pollExpired() { + RunnableScheduledFuture first = queue[0]; + if (first == null || first.getDelay(TimeUnit.NANOSECONDS) > 0) + return null; + return finishPoll(first); + } + + public int drainTo(Collection c) { + if (c == null) + throw new NullPointerException(); + if (c == this) + throw new IllegalArgumentException(); + final ReentrantLock lock = this.lock; + lock.lock(); + try { + RunnableScheduledFuture first; + int n = 0; + while ((first = pollExpired()) != null) { + c.add(first); + ++n; + } + return n; + } finally { + lock.unlock(); + } } - public int remainingCapacity() { return dq.remainingCapacity(); } - public boolean remove(Object x) { return dq.remove(x); } - public boolean contains(Object x) { return dq.contains(x); } - public int size() { return dq.size(); } - public boolean isEmpty() { return dq.isEmpty(); } - public Object[] toArray() { return dq.toArray(); } - public T[] toArray(T[] array) { return dq.toArray(array); } + public int drainTo(Collection c, int maxElements) { + if (c == null) + throw new NullPointerException(); + if (c == this) + throw new IllegalArgumentException(); + if (maxElements <= 0) + return 0; + final ReentrantLock lock = this.lock; + lock.lock(); + try { + RunnableScheduledFuture first; + int n = 0; + while (n < maxElements && (first = pollExpired()) != null) { + c.add(first); + ++n; + } + return n; + } finally { + lock.unlock(); + } + } + + public Object[] toArray() { + final ReentrantLock lock = this.lock; + lock.lock(); + try { + return Arrays.copyOf(queue, size, Object[].class); + } finally { + lock.unlock(); + } + } + + @SuppressWarnings("unchecked") + public T[] toArray(T[] a) { + final ReentrantLock lock = this.lock; + lock.lock(); + try { + if (a.length < size) + return (T[]) Arrays.copyOf(queue, size, a.getClass()); + System.arraycopy(queue, 0, a, 0, size); + if (a.length > size) + a[size] = null; + return a; + } finally { + lock.unlock(); + } + } + public Iterator iterator() { - return new Iterator() { - private Iterator it = dq.iterator(); - public boolean hasNext() { return it.hasNext(); } - public Runnable next() { return it.next(); } - public void remove() { it.remove(); } - }; + return new Itr(Arrays.copyOf(queue, size)); + } + + /** + * Snapshot iterator that works off copy of underlying q array. + */ + private class Itr implements Iterator { + final RunnableScheduledFuture[] array; + int cursor = 0; // index of next element to return + int lastRet = -1; // index of last element, or -1 if no such + + Itr(RunnableScheduledFuture[] array) { + this.array = array; + } + + public boolean hasNext() { + return cursor < array.length; + } + + public Runnable next() { + if (cursor >= array.length) + throw new NoSuchElementException(); + lastRet = cursor; + return array[cursor++]; + } + + public void remove() { + if (lastRet < 0) + throw new IllegalStateException(); + DelayedWorkQueue.this.remove(array[lastRet]); + lastRet = -1; + } } } } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java --- a/jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java Tue Mar 11 23:37:02 2008 -0700 @@ -1342,6 +1342,10 @@ * tasks are executed, but no new tasks will be accepted. * Invocation has no additional effect if already shut down. * + *

    This method does not wait for previously submitted tasks to + * complete execution. Use {@link #awaitTermination awaitTermination} + * to do that. + * * @throws SecurityException {@inheritDoc} */ public void shutdown() { @@ -1364,6 +1368,10 @@ * that were awaiting execution. These tasks are drained (removed) * from the task queue upon return from this method. * + *

    This method does not wait for actively executing tasks to + * terminate. Use {@link #awaitTermination awaitTermination} to + * do that. + * *

    There are no guarantees beyond best-effort attempts to stop * processing actively executing tasks. This implementation * cancels tasks via {@link Thread#interrupt}, so any task that diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java --- a/jdk/src/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java Tue Mar 11 23:37:02 2008 -0700 @@ -222,7 +222,7 @@ /** Inner class providing writelock */ private final ReentrantReadWriteLock.WriteLock writerLock; /** Performs all synchronization mechanics */ - private final Sync sync; + final Sync sync; /** * Creates a new {@code ReentrantReadWriteLock} with @@ -239,7 +239,7 @@ * @param fair {@code true} if this lock should use a fair ordering policy */ public ReentrantReadWriteLock(boolean fair) { - sync = (fair)? new FairSync() : new NonfairSync(); + sync = fair ? new FairSync() : new NonfairSync(); readerLock = new ReadLock(this); writerLock = new WriteLock(this); } @@ -256,8 +256,8 @@ /* * Read vs write count extraction constants and functions. - * Lock state is logically divided into two shorts: The lower - * one representing the exclusive (writer) lock hold count, + * Lock state is logically divided into two unsigned shorts: + * The lower one representing the exclusive (writer) lock hold count, * and the upper the shared (reader) hold count. */ @@ -279,13 +279,6 @@ int count; // Use id, not reference, to avoid garbage retention final long tid = Thread.currentThread().getId(); - /** Decrement if positive; return previous value */ - int tryDecrement() { - int c = count; - if (c > 0) - count = c - 1; - return c; - } } /** @@ -303,7 +296,7 @@ * The number of read locks held by current thread. * Initialized only in constructor and readObject. */ - transient ThreadLocalHoldCounter readHolds; + private transient ThreadLocalHoldCounter readHolds; /** * The hold count of the last thread to successfully acquire @@ -312,7 +305,17 @@ * acquire. This is non-volatile since it is just used * as a heuristic, and would be great for threads to cache. */ - transient HoldCounter cachedHoldCounter; + private transient HoldCounter cachedHoldCounter; + + /** + * firstReader is the first thread to have acquired the read lock. + * firstReaderHoldCount is firstReader's hold count. + * This allows tracking of read holds for uncontended read + * locks to be very cheap. + */ + private final static long INVALID_THREAD_ID = -1; + private transient long firstReader = INVALID_THREAD_ID; + private transient int firstReaderHoldCount; Sync() { readHolds = new ThreadLocalHoldCounter(); @@ -390,12 +393,25 @@ } protected final boolean tryReleaseShared(int unused) { - HoldCounter rh = cachedHoldCounter; - Thread current = Thread.currentThread(); - if (rh == null || rh.tid != current.getId()) - rh = readHolds.get(); - if (rh.tryDecrement() <= 0) - throw new IllegalMonitorStateException(); + long tid = Thread.currentThread().getId(); + if (firstReader == tid) { + // assert firstReaderHoldCount > 0; + if (firstReaderHoldCount == 1) + firstReader = INVALID_THREAD_ID; + else + firstReaderHoldCount--; + } else { + HoldCounter rh = cachedHoldCounter; + if (rh == null || rh.tid != tid) + rh = readHolds.get(); + int count = rh.count; + if (count <= 1) { + readHolds.remove(); + if (count <= 0) + throw unmatchedUnlockException(); + } + --rh.count; + } for (;;) { int c = getState(); int nextc = c - SHARED_UNIT; @@ -404,12 +420,16 @@ } } + private IllegalMonitorStateException unmatchedUnlockException() { + return new IllegalMonitorStateException( + "attempt to unlock read lock, not locked by current thread"); + } + protected final int tryAcquireShared(int unused) { /* * Walkthrough: * 1. If write lock held by another thread, fail. - * 2. If count saturated, throw error. - * 3. Otherwise, this thread is eligible for + * 2. Otherwise, this thread is eligible for * lock wrt state, so ask if it should block * because of queue policy. If not, try * to grant by CASing state and updating count. @@ -417,23 +437,33 @@ * acquires, which is postponed to full version * to avoid having to check hold count in * the more typical non-reentrant case. - * 4. If step 3 fails either because thread - * apparently not eligible or CAS fails, - * chain to version with full retry loop. + * 3. If step 2 fails either because thread + * apparently not eligible or CAS fails or count + * saturated, chain to version with full retry loop. */ Thread current = Thread.currentThread(); int c = getState(); if (exclusiveCount(c) != 0 && getExclusiveOwnerThread() != current) return -1; - if (sharedCount(c) == MAX_COUNT) - throw new Error("Maximum lock count exceeded"); + int r = sharedCount(c); if (!readerShouldBlock() && + r < MAX_COUNT && compareAndSetState(c, c + SHARED_UNIT)) { - HoldCounter rh = cachedHoldCounter; - if (rh == null || rh.tid != current.getId()) - cachedHoldCounter = rh = readHolds.get(); - rh.count++; + long tid = current.getId(); + if (r == 0) { + firstReader = tid; + firstReaderHoldCount = 1; + } else if (firstReader == tid) { + firstReaderHoldCount++; + } else { + HoldCounter rh = cachedHoldCounter; + if (rh == null || rh.tid != tid) + cachedHoldCounter = rh = readHolds.get(); + else if (rh.count == 0) + readHolds.set(rh); + rh.count++; + } return 1; } return fullTryAcquireShared(current); @@ -450,20 +480,56 @@ * complicating tryAcquireShared with interactions between * retries and lazily reading hold counts. */ - HoldCounter rh = cachedHoldCounter; - if (rh == null || rh.tid != current.getId()) - rh = readHolds.get(); + HoldCounter rh = null; for (;;) { int c = getState(); - int w = exclusiveCount(c); - if ((w != 0 && getExclusiveOwnerThread() != current) || - ((rh.count | w) == 0 && readerShouldBlock())) - return -1; + if (exclusiveCount(c) != 0) { + if (getExclusiveOwnerThread() != current) + //if (removeNeeded) readHolds.remove(); + return -1; + // else we hold the exclusive lock; blocking here + // would cause deadlock. + } else if (readerShouldBlock()) { + // Make sure we're not acquiring read lock reentrantly + long tid = current.getId(); + if (firstReader == tid) { + // assert firstReaderHoldCount > 0; + } else { + if (rh == null) { + rh = cachedHoldCounter; + if (rh == null || rh.tid != tid) { + rh = readHolds.get(); + if (rh.count == 0) + readHolds.remove(); + } + } + if (rh.count == 0) + return -1; + } + } if (sharedCount(c) == MAX_COUNT) throw new Error("Maximum lock count exceeded"); if (compareAndSetState(c, c + SHARED_UNIT)) { - cachedHoldCounter = rh; // cache for release - rh.count++; + long tid = current.getId(); + if (sharedCount(c) == 0) { + firstReader = tid; + firstReaderHoldCount = 1; + } else if (firstReader == tid) { + firstReaderHoldCount++; + } else { + if (rh == null) { + rh = cachedHoldCounter; + if (rh != null && rh.tid == tid) { + if (rh.count == 0) + readHolds.set(rh); + } else { + rh = readHolds.get(); + } + } else if (rh.count == 0) + readHolds.set(rh); + cachedHoldCounter = rh; // cache for release + rh.count++; + } return 1; } } @@ -472,14 +538,14 @@ /** * Performs tryLock for write, enabling barging in both modes. * This is identical in effect to tryAcquire except for lack - * of calls to writerShouldBlock + * of calls to writerShouldBlock. */ final boolean tryWriteLock() { Thread current = Thread.currentThread(); int c = getState(); if (c != 0) { int w = exclusiveCount(c); - if (w == 0 ||current != getExclusiveOwnerThread()) + if (w == 0 || current != getExclusiveOwnerThread()) return false; if (w == MAX_COUNT) throw new Error("Maximum lock count exceeded"); @@ -493,7 +559,7 @@ /** * Performs tryLock for read, enabling barging in both modes. * This is identical in effect to tryAcquireShared except for - * lack of calls to readerShouldBlock + * lack of calls to readerShouldBlock. */ final boolean tryReadLock() { Thread current = Thread.currentThread(); @@ -502,13 +568,24 @@ if (exclusiveCount(c) != 0 && getExclusiveOwnerThread() != current) return false; - if (sharedCount(c) == MAX_COUNT) + int r = sharedCount(c); + if (r == MAX_COUNT) throw new Error("Maximum lock count exceeded"); if (compareAndSetState(c, c + SHARED_UNIT)) { - HoldCounter rh = cachedHoldCounter; - if (rh == null || rh.tid != current.getId()) - cachedHoldCounter = rh = readHolds.get(); - rh.count++; + long tid = current.getId(); + if (r == 0) { + firstReader = tid; + firstReaderHoldCount = 1; + } else if (firstReader == tid) { + firstReaderHoldCount++; + } else { + HoldCounter rh = cachedHoldCounter; + if (rh == null || rh.tid != tid) + cachedHoldCounter = rh = readHolds.get(); + else if (rh.count == 0) + readHolds.set(rh); + rh.count++; + } return true; } } @@ -546,7 +623,20 @@ } final int getReadHoldCount() { - return getReadLockCount() == 0? 0 : readHolds.get().count; + if (getReadLockCount() == 0) + return 0; + + long tid = Thread.currentThread().getId(); + if (firstReader == tid) + return firstReaderHoldCount; + + HoldCounter rh = cachedHoldCounter; + if (rh != null && rh.tid == tid) + return rh.count; + + int count = readHolds.get().count; + if (count == 0) readHolds.remove(); + return count; } /** @@ -557,6 +647,7 @@ throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); readHolds = new ThreadLocalHoldCounter(); + firstReader = INVALID_THREAD_ID; setState(0); // reset to unlocked state } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/util/prefs/AbstractPreferences.java --- a/jdk/src/share/classes/java/util/prefs/AbstractPreferences.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/util/prefs/AbstractPreferences.java Tue Mar 11 23:37:02 2008 -0700 @@ -155,7 +155,8 @@ * All known unremoved children of this node. (This "cache" is consulted * prior to calling childSpi() or getChild(). */ - private Map kidCache = new HashMap(); + private Map kidCache + = new HashMap(); /** * This field is used to keep track of whether or not this node has @@ -712,11 +713,10 @@ if (removed) throw new IllegalStateException("Node has been removed."); - Set s = new TreeSet(kidCache.keySet()); - String[] kids = childrenNamesSpi(); - for(int i=0; i s = new TreeSet(kidCache.keySet()); + for (String kid : childrenNamesSpi()) + s.add(kid); + return s.toArray(EMPTY_STRING_ARRAY); } } @@ -728,8 +728,7 @@ * @return all known unremoved children of this node. */ protected final AbstractPreferences[] cachedChildren() { - return (AbstractPreferences[]) kidCache.values(). - toArray(EMPTY_ABSTRACT_PREFS_ARRAY); + return kidCache.values().toArray(EMPTY_ABSTRACT_PREFS_ARRAY); } private static final AbstractPreferences[] EMPTY_ABSTRACT_PREFS_ARRAY @@ -825,7 +824,7 @@ if (token.equals("/")) // Check for consecutive slashes throw new IllegalArgumentException("Consecutive slashes in path"); synchronized(lock) { - AbstractPreferences child=(AbstractPreferences)kidCache.get(token); + AbstractPreferences child = kidCache.get(token); if (child == null) { if (token.length() > MAX_NAME_LENGTH) throw new IllegalArgumentException( @@ -893,7 +892,7 @@ if (token.equals("/")) // Check for consecutive slashes throw new IllegalArgumentException("Consecutive slashes in path"); synchronized(lock) { - AbstractPreferences child=(AbstractPreferences)kidCache.get(token); + AbstractPreferences child = kidCache.get(token); if (child == null) child = getChild(token); if (child==null) @@ -964,9 +963,10 @@ kidCache.put(kidNames[i], childSpi(kidNames[i])); // Recursively remove all cached children - for (Iterator i = kidCache.values().iterator(); i.hasNext();) { + for (Iterator i = kidCache.values().iterator(); + i.hasNext();) { try { - ((AbstractPreferences)i.next()).removeNode2(); + i.next().removeNode2(); i.remove(); } catch (BackingStoreException x) { } } @@ -1020,13 +1020,12 @@ * preference tree. */ public boolean isUserNode() { - Boolean result = (Boolean) - AccessController.doPrivileged( new PrivilegedAction() { - public Object run() { - return Boolean.valueOf(root == Preferences.userRoot()); + return AccessController.doPrivileged( + new PrivilegedAction() { + public Boolean run() { + return root == Preferences.userRoot(); } - }); - return result.booleanValue(); + }).booleanValue(); } public void addPreferenceChangeListener(PreferenceChangeListener pcl) { @@ -1443,7 +1442,8 @@ * event delivery from preference activity, greatly simplifying * locking and reducing opportunity for deadlock. */ - private static final List eventQueue = new LinkedList(); + private static final List eventQueue + = new LinkedList(); /** * These two classes are used to distinguish NodeChangeEvents on @@ -1476,7 +1476,7 @@ try { while (eventQueue.isEmpty()) eventQueue.wait(); - event = (EventObject) eventQueue.remove(0); + event = eventQueue.remove(0); } catch (InterruptedException e) { // XXX Log "Event dispatch thread interrupted. Exiting" return; diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/java/util/regex/Matcher.java --- a/jdk/src/share/classes/java/util/regex/Matcher.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/java/util/regex/Matcher.java Tue Mar 11 23:37:02 2008 -0700 @@ -249,7 +249,7 @@ Matcher result = new Matcher(this.parentPattern, text.toString()); result.first = this.first; result.last = this.last; - result.groups = (int[])(this.groups.clone()); + result.groups = this.groups.clone(); return result; } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/javax/management/AndQueryExp.java --- a/jdk/src/share/classes/javax/management/AndQueryExp.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/javax/management/AndQueryExp.java Tue Mar 11 23:37:02 2008 -0700 @@ -104,4 +104,25 @@ return "(" + exp1 + ") and (" + exp2 + ")"; } - } + @Override + String toQueryString() { + // Parentheses are only added if needed to disambiguate. + return parens(exp1) + " and " + parens(exp2); + } + + // Add parens if needed to disambiguate an expression such as + // Query.and(Query.or(a, b), c). We need to return + // (a or b) and c + // in such a case, because + // a or b and c + // would mean + // a or (b and c) + private static String parens(QueryExp exp) { + String s = Query.toString(exp); + if (exp instanceof OrQueryExp) + return "(" + s + ")"; + else + return s; + } + +} diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/javax/management/AttributeValueExp.java --- a/jdk/src/share/classes/javax/management/AttributeValueExp.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/javax/management/AttributeValueExp.java Tue Mar 11 23:37:02 2008 -0700 @@ -26,12 +26,17 @@ package javax.management; -// RI import -import javax.management.MBeanServer; +import com.sun.jmx.mbeanserver.Introspector; +import java.io.IOException; +import java.io.ObjectInputStream; /** - * Represents attributes used as arguments to relational constraints. - * An AttributeValueExp may be used anywhere a ValueExp is required. + *

    Represents attributes used as arguments to relational constraints. + * Instances of this class are usually obtained using {@link Query#attr(String) + * Query.attr}.

    + * + *

    An AttributeValueExp may be used anywhere a + * ValueExp is required. * * @since 1.5 */ @@ -46,6 +51,8 @@ */ private String attr; + private transient int dotIndex; + /** * An AttributeValueExp with a null attribute. * @deprecated An instance created with this constructor cannot be @@ -64,6 +71,18 @@ */ public AttributeValueExp(String attr) { this.attr = attr; + setDotIndex(); + } + + private void setDotIndex() { + if (attr != null) + dotIndex = attr.indexOf('.'); + } + + private void readObject(ObjectInputStream in) + throws ClassNotFoundException, IOException { + in.defaultReadObject(); + setDotIndex(); } /** @@ -76,7 +95,13 @@ } /** - * Applies the AttributeValueExp on an MBean. + *

    Applies the AttributeValueExp on an MBean. + * This method calls {@link #getAttribute getAttribute(name)} and wraps + * the result as a {@code ValueExp}. The value returned by + * {@code getAttribute} must be a {@code Number}, {@code String}, + * or {@code Boolean}; otherwise this method throws a + * {@code BadAttributeValueExpException}, which will cause + * the containing query to be false for this {@code name}.

    * * @param name The name of the MBean on which the AttributeValueExp will be applied. * @@ -88,6 +113,7 @@ * @exception BadBinaryOpValueExpException * */ + @Override public ValueExp apply(ObjectName name) throws BadStringOperationException, BadBinaryOpValueExpException, BadAttributeValueExpException, InvalidApplicationException { Object result = getAttribute(name); @@ -106,8 +132,9 @@ /** * Returns the string representing its value. */ + @Override public String toString() { - return attr; + return QueryParser.quoteId(attr); } @@ -115,18 +142,38 @@ * Sets the MBean server on which the query is to be performed. * * @param s The MBean server on which the query is to be performed. + * + * @deprecated This method has no effect. The MBean Server used to + * obtain an attribute value is {@link QueryEval#getMBeanServer()}. */ /* There is no need for this method, because if a query is being evaluted an AttributeValueExp can only appear inside a QueryExp, and that QueryExp will itself have done setMBeanServer. */ + @Deprecated + @Override public void setMBeanServer(MBeanServer s) { } /** - * Return the value of the given attribute in the named MBean. + *

    Return the value of the given attribute in the named MBean. * If the attempt to access the attribute generates an exception, - * return null. + * return null.

    + * + *

    Let n be the {@linkplain #getAttributeName attribute + * name}. Then this method proceeds as follows. First it calls + * {@link MBeanServer#getAttribute getAttribute(name, n)}. If that + * generates an {@link AttributeNotFoundException}, and if n + * contains at least one dot ({@code .}), then the method calls {@code + * getAttribute(name, }n{@code .substring(0, }n{@code + * .indexOf('.')))}; in other words it calls {@code getAttribute} + * with the substring of n before the first dot. Then it + * extracts a component from the retrieved value, as described in the documentation for the {@code + * monitor} package.

    + * + *

    The MBean Server used is the one returned by {@link + * QueryEval#getMBeanServer()}.

    * * @param name the name of the MBean whose attribute is to be returned. * @@ -139,10 +186,34 @@ MBeanServer server = QueryEval.getMBeanServer(); + try { return server.getAttribute(name, attr); + } catch (AttributeNotFoundException e) { + if (dotIndex < 0) + throw e; + } + + String toGet = attr.substring(0, dotIndex); + + Object value = server.getAttribute(name, toGet); + + return extractElement(value, attr.substring(dotIndex + 1)); } catch (Exception re) { return null; } } + private Object extractElement(Object value, String elementWithDots) + throws AttributeNotFoundException { + while (true) { + int dot = elementWithDots.indexOf('.'); + String element = (dot < 0) ? + elementWithDots : elementWithDots.substring(0, dot); + value = Introspector.elementFromComplex(value, element); + if (dot < 0) + return value; + elementWithDots = elementWithDots.substring(dot + 1); + } + } + } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/javax/management/BetweenQueryExp.java --- a/jdk/src/share/classes/javax/management/BetweenQueryExp.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/javax/management/BetweenQueryExp.java Tue Mar 11 23:37:02 2008 -0700 @@ -109,34 +109,25 @@ ValueExp val1 = exp1.apply(name); ValueExp val2 = exp2.apply(name); ValueExp val3 = exp3.apply(name); - String sval1; - String sval2; - String sval3; - double dval1; - double dval2; - double dval3; - long lval1; - long lval2; - long lval3; boolean numeric = val1 instanceof NumericValueExp; if (numeric) { if (((NumericValueExp)val1).isLong()) { - lval1 = ((NumericValueExp)val1).longValue(); - lval2 = ((NumericValueExp)val2).longValue(); - lval3 = ((NumericValueExp)val3).longValue(); + long lval1 = ((NumericValueExp)val1).longValue(); + long lval2 = ((NumericValueExp)val2).longValue(); + long lval3 = ((NumericValueExp)val3).longValue(); return lval2 <= lval1 && lval1 <= lval3; } else { - dval1 = ((NumericValueExp)val1).doubleValue(); - dval2 = ((NumericValueExp)val2).doubleValue(); - dval3 = ((NumericValueExp)val3).doubleValue(); + double dval1 = ((NumericValueExp)val1).doubleValue(); + double dval2 = ((NumericValueExp)val2).doubleValue(); + double dval3 = ((NumericValueExp)val3).doubleValue(); return dval2 <= dval1 && dval1 <= dval3; } } else { - sval1 = ((StringValueExp)val1).toString(); - sval2 = ((StringValueExp)val2).toString(); - sval3 = ((StringValueExp)val3).toString(); + String sval1 = ((StringValueExp)val1).getValue(); + String sval2 = ((StringValueExp)val2).getValue(); + String sval3 = ((StringValueExp)val3).getValue(); return sval2.compareTo(sval1) <= 0 && sval1.compareTo(sval3) <= 0; } } @@ -148,4 +139,8 @@ return "(" + exp1 + ") between (" + exp2 + ") and (" + exp3 + ")"; } - } + @Override + String toQueryString() { + return exp1 + " between " + exp2 + " and " + exp3; + } +} diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/javax/management/BinaryOpValueExp.java --- a/jdk/src/share/classes/javax/management/BinaryOpValueExp.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/javax/management/BinaryOpValueExp.java Tue Mar 11 23:37:02 2008 -0700 @@ -167,12 +167,74 @@ */ public String toString() { try { - return exp1 + " " + opString() + " " + exp2; + return parens(exp1, true) + " " + opString() + " " + parens(exp2, false); } catch (BadBinaryOpValueExpException ex) { return "invalid expression"; } } + /* + * Add parentheses to the given subexpression if necessary to + * preserve meaning. Suppose this BinaryOpValueExp is + * Query.times(Query.plus(Query.attr("A"), Query.attr("B")), Query.attr("C")). + * Then the original toString() logic would return A + B * C. + * We check precedences in order to return (A + B) * C, which is the + * meaning of the ValueExp. + * + * We need to add parentheses if the unparenthesized expression would + * be parsed as a different ValueExp from the original. + * We cannot omit parentheses even when mathematically + * the result would be equivalent, because we do not know whether the + * numeric values will be integer or floating-point. Addition and + * multiplication are associative for integers but not always for + * floating-point. + * + * So the rule is that we omit parentheses if the ValueExp + * is (A op1 B) op2 C and the precedence of op1 is greater than or + * equal to that of op2; or if the ValueExp is A op1 (B op2 C) and + * the precedence of op2 is greater than that of op1. (There are two + * precedences: that of * and / is greater than that of + and -.) + * The case of (A op1 B) op2 (C op3 D) applies each rule in turn. + * + * The following examples show the rules in action. On the left, + * the original ValueExp. On the right, the string representation. + * + * (A + B) + C A + B + C + * (A * B) + C A * B + C + * (A + B) * C (A + B) * C + * (A * B) * C A * B * C + * A + (B + C) A + (B + C) + * A + (B * C) A + B * C + * A * (B + C) A * (B + C) + * A * (B * C) A * (B * C) + */ + private String parens(ValueExp subexp, boolean left) + throws BadBinaryOpValueExpException { + boolean omit; + if (subexp instanceof BinaryOpValueExp) { + int subop = ((BinaryOpValueExp) subexp).op; + if (left) + omit = (precedence(subop) >= precedence(op)); + else + omit = (precedence(subop) > precedence(op)); + } else + omit = true; + + if (omit) + return subexp.toString(); + else + return "(" + subexp + ")"; + } + + private int precedence(int xop) throws BadBinaryOpValueExpException { + switch (xop) { + case Query.PLUS: case Query.MINUS: return 0; + case Query.TIMES: case Query.DIV: return 1; + default: + throw new BadBinaryOpValueExpException(this); + } + } + private String opString() throws BadBinaryOpValueExpException { switch (op) { case Query.PLUS: @@ -188,4 +250,10 @@ throw new BadBinaryOpValueExpException(this); } + @Deprecated + public void setMBeanServer(MBeanServer s) { + super.setMBeanServer(s); } + + + } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/javax/management/BinaryRelQueryExp.java --- a/jdk/src/share/classes/javax/management/BinaryRelQueryExp.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/javax/management/BinaryRelQueryExp.java Tue Mar 11 23:37:02 2008 -0700 @@ -108,20 +108,12 @@ BadAttributeValueExpException, InvalidApplicationException { Object val1 = exp1.apply(name); Object val2 = exp2.apply(name); - String sval1; - String sval2; - double dval1; - double dval2; - long lval1; - long lval2; - boolean bval1; - boolean bval2; boolean numeric = val1 instanceof NumericValueExp; boolean bool = val1 instanceof BooleanValueExp; if (numeric) { if (((NumericValueExp)val1).isLong()) { - lval1 = ((NumericValueExp)val1).longValue(); - lval2 = ((NumericValueExp)val2).longValue(); + long lval1 = ((NumericValueExp)val1).longValue(); + long lval2 = ((NumericValueExp)val2).longValue(); switch (relOp) { case Query.GT: @@ -136,8 +128,8 @@ return lval1 == lval2; } } else { - dval1 = ((NumericValueExp)val1).doubleValue(); - dval2 = ((NumericValueExp)val2).doubleValue(); + double dval1 = ((NumericValueExp)val1).doubleValue(); + double dval2 = ((NumericValueExp)val2).doubleValue(); switch (relOp) { case Query.GT: @@ -155,8 +147,8 @@ } else if (bool) { - bval1 = ((BooleanValueExp)val1).getValue().booleanValue(); - bval2 = ((BooleanValueExp)val2).getValue().booleanValue(); + boolean bval1 = ((BooleanValueExp)val1).getValue().booleanValue(); + boolean bval2 = ((BooleanValueExp)val2).getValue().booleanValue(); switch (relOp) { case Query.GT: @@ -172,8 +164,8 @@ } } else { - sval1 = ((StringValueExp)val1).getValue(); - sval2 = ((StringValueExp)val2).getValue(); + String sval1 = ((StringValueExp)val1).getValue(); + String sval2 = ((StringValueExp)val2).getValue(); switch (relOp) { case Query.GT: @@ -199,6 +191,11 @@ return "(" + exp1 + ") " + relOpString() + " (" + exp2 + ")"; } + @Override + String toQueryString() { + return exp1 + " " + relOpString() + " " + exp2; + } + private String relOpString() { switch (relOp) { case Query.GT: diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/javax/management/BooleanValueExp.java --- a/jdk/src/share/classes/javax/management/BooleanValueExp.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/javax/management/BooleanValueExp.java Tue Mar 11 23:37:02 2008 -0700 @@ -84,4 +84,10 @@ return this; } + @Deprecated + public void setMBeanServer(MBeanServer s) { + super.setMBeanServer(s); + } + + } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/javax/management/InQueryExp.java --- a/jdk/src/share/classes/javax/management/InQueryExp.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/javax/management/InQueryExp.java Tue Mar 11 23:37:02 2008 -0700 @@ -91,21 +91,23 @@ * @exception BadAttributeValueExpException * @exception InvalidApplicationException */ - public boolean apply(ObjectName name) throws BadStringOperationException, BadBinaryOpValueExpException, + public boolean apply(ObjectName name) + throws BadStringOperationException, BadBinaryOpValueExpException, BadAttributeValueExpException, InvalidApplicationException { if (valueList != null) { ValueExp v = val.apply(name); boolean numeric = v instanceof NumericValueExp; - for (int i = 0; i < valueList.length; i++) { + for (ValueExp element : valueList) { + element = element.apply(name); if (numeric) { - if (((NumericValueExp)valueList[i]).doubleValue() == - ((NumericValueExp)v).doubleValue()) { + if (((NumericValueExp) element).doubleValue() == + ((NumericValueExp) v).doubleValue()) { return true; } } else { - if (((StringValueExp)valueList[i]).getValue().equals( - ((StringValueExp)v).getValue())) { + if (((StringValueExp) element).getValue().equals( + ((StringValueExp) v).getValue())) { return true; } } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/javax/management/MatchQueryExp.java --- a/jdk/src/share/classes/javax/management/MatchQueryExp.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/javax/management/MatchQueryExp.java Tue Mar 11 23:37:02 2008 -0700 @@ -113,7 +113,32 @@ } private static String likeTranslate(String s) { - return s.replace('?', '_').replace('*', '%'); + StringBuilder sb = new StringBuilder(); + int c; + for (int i = 0; i < s.length(); i += Character.charCount(c)) { + c = s.codePointAt(i); + switch (c) { + case '\\': + i += Character.charCount(c); + sb.append('\\'); + if (i < s.length()) { + c = s.codePointAt(i); + sb.appendCodePoint(c); + } + break; + case '*': + sb.append('%'); break; + case '?': + sb.append('_'); break; + case '%': + sb.append("\\%"); break; + case '_': + sb.append("\\_"); break; + default: + sb.appendCodePoint(c); break; + } + } + return sb.toString(); } /* diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/javax/management/NotQueryExp.java --- a/jdk/src/share/classes/javax/management/NotQueryExp.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/javax/management/NotQueryExp.java Tue Mar 11 23:37:02 2008 -0700 @@ -86,8 +86,14 @@ /** * Returns the string representing the object. */ + @Override public String toString() { return "not (" + exp + ")"; } + @Override + String toQueryString() { + return "not (" + Query.toString(exp) + ")"; + } + } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/javax/management/NumericValueExp.java --- a/jdk/src/share/classes/javax/management/NumericValueExp.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/javax/management/NumericValueExp.java Tue Mar 11 23:37:02 2008 -0700 @@ -151,11 +151,18 @@ * Returns the string representing the object */ public String toString() { + if (val == null) + return "null"; if (val instanceof Long || val instanceof Integer) { - return String.valueOf(val.longValue()); + return Long.toString(val.longValue()); } - return String.valueOf(val.doubleValue()); + double d = val.doubleValue(); + if (Double.isInfinite(d)) + return (d > 0) ? "(1.0 / 0.0)" : "(-1.0 / 0.0)"; + if (Double.isNaN(d)) + return "(0.0 / 0.0)"; + return Double.toString(d); } /** @@ -244,4 +251,10 @@ out.defaultWriteObject(); } } + + @Deprecated + public void setMBeanServer(MBeanServer s) { + super.setMBeanServer(s); + } + } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/javax/management/ObjectName.java --- a/jdk/src/share/classes/javax/management/ObjectName.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/javax/management/ObjectName.java Tue Mar 11 23:37:02 2008 -0700 @@ -222,7 +222,8 @@ * @since 1.5 */ @SuppressWarnings("serial") // don't complain serialVersionUID not constant -public class ObjectName implements Comparable, QueryExp { +public class ObjectName extends ToQueryString + implements Comparable, QueryExp { /** * A structure recording property structure and @@ -1779,10 +1780,16 @@ * * @return a string representation of this object name. */ + @Override public String toString() { return getSerializedNameString(); } + @Override + String toQueryString() { + return "LIKE " + Query.value(toString()); + } + /** * Compares the current object name with another object name. Two * ObjectName instances are equal if and only if their canonical diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/javax/management/OrQueryExp.java --- a/jdk/src/share/classes/javax/management/OrQueryExp.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/javax/management/OrQueryExp.java Tue Mar 11 23:37:02 2008 -0700 @@ -98,9 +98,29 @@ } /** - * Returns a string representation of this AndQueryExp + * Returns a string representation of this OrQueryExp */ public String toString() { return "(" + exp1 + ") or (" + exp2 + ")"; } + + @Override + String toQueryString() { + return parens(exp1) + " or " + parens(exp2); + } + + // Add parentheses to avoid possible confusion. If we have an expression + // such as Query.or(Query.and(a, b), c), then we return + // (a and b) or c + // rather than just + // a and b or c + // In fact the precedence rules are such that the parentheses are not + // strictly necessary, but omitting them would be confusing. + private static String parens(QueryExp exp) { + String s = Query.toString(exp); + if (exp instanceof AndQueryExp) + return "(" + s + ")"; + else + return s; + } } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/javax/management/QualifiedAttributeValueExp.java --- a/jdk/src/share/classes/javax/management/QualifiedAttributeValueExp.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/javax/management/QualifiedAttributeValueExp.java Tue Mar 11 23:37:02 2008 -0700 @@ -27,9 +27,11 @@ /** - * This class represents indexed attributes used as arguments to relational - * constraints. An QualifiedAttributeValueExp may be used anywhere a - * ValueExp is required. + *

    Represents attributes used as arguments to relational constraints, + * where the attribute must be in an MBean of a specified {@linkplain + * MBeanInfo#getClassName() class}. A QualifiedAttributeValueExp may be used + * anywhere a ValueExp is required. + * * @serial include * * @since 1.5 @@ -48,7 +50,9 @@ /** * Basic Constructor. + * @deprecated see {@link AttributeValueExp#AttributeValueExp()} */ + @Deprecated public QualifiedAttributeValueExp() { } @@ -81,6 +85,7 @@ * @exception BadAttributeValueExpException * @exception InvalidApplicationException */ + @Override public ValueExp apply(ObjectName name) throws BadStringOperationException, BadBinaryOpValueExpException, BadAttributeValueExpException, InvalidApplicationException { try { @@ -105,9 +110,11 @@ /** * Returns the string representing its value */ + @Override public String toString() { if (className != null) { - return className + "." + super.toString(); + return QueryParser.quoteId(className) + "#" + + QueryParser.quoteId(super.toString()); } else { return super.toString(); } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/javax/management/Query.java --- a/jdk/src/share/classes/javax/management/Query.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/javax/management/Query.java Tue Mar 11 23:37:02 2008 -0700 @@ -27,19 +27,346 @@ /** - *

    Constructs query object constraints. The static methods provided - * return query expressions that may be used in listing and - * enumerating MBeans. Individual constraint construction methods - * allow only appropriate types as arguments. Composition of calls can - * construct arbitrary nestings of constraints, as the following - * example illustrates:

    + *

    Constructs query object constraints.

    + * + *

    The MBean Server can be queried for MBeans that meet a particular + * condition, using its {@link MBeanServer#queryNames queryNames} or + * {@link MBeanServer#queryMBeans queryMBeans} method. The {@link QueryExp} + * parameter to the method can be any implementation of the interface + * {@code QueryExp}, but it is usually best to obtain the {@code QueryExp} + * value by calling the static methods in this class. This is particularly + * true when querying a remote MBean Server: a custom implementation of the + * {@code QueryExp} interface might not be present in the remote MBean Server, + * but the methods in this class return only standard classes that are + * part of the JMX implementation.

    + * + *

    There are two ways to create {@code QueryExp} objects using the methods + * in this class. The first is to build them by chaining together calls to + * the various methods. The second is to use the Query Language described + * below and produce the {@code QueryExp} by calling + * {@link #fromString Query.fromString}. The two ways are equivalent: + * every {@code QueryExp} returned by {@code fromString} can also be + * constructed by chaining method calls.

    + * + *

    As an example, suppose you wanted to find all MBeans where the {@code + * Enabled} attribute is {@code true} and the {@code Owner} attribute is {@code + * "Duke"}. Here is how you could construct the appropriate {@code QueryExp} by + * chaining together method calls:

    + * + *
    + * QueryExp query =
    + *     Query.and(Query.eq(Query.attr("Enabled"), Query.value(true)),
    + *               Query.eq(Query.attr("Owner"), Query.value("Duke")));
    + * 
    + * + *

    Here is how you could construct the same {@code QueryExp} using the + * Query Language:

    * *
    - * QueryExp exp = Query.and(Query.gt(Query.attr("age"),Query.value(5)),
    - *                          Query.match(Query.attr("name"),
    - *                                      Query.value("Smith")));
    + * QueryExp query = Query.fromString("Enabled = true and Owner = 'Duke'");
      * 
    * + *

    The principal advantage of the method-chaining approach is that the + * compiler will check that the query makes sense. The principal advantage + * of the Query Language approach is that it is easier to write and especially + * read.

    + * + * + *

    Query Language

    + * + *

    The query language is closely modeled on the WHERE clause of + * SQL SELECT statements. The formal specification of the language + * appears below, but it is probably easier to + * understand it with examples such as the following.

    + * + *
    + *
    {@code Message = 'OK'} + *
    Selects MBeans that have a {@code Message} attribute whose value + * is the string {@code OK}. + * + *
    {@code FreeSpacePercent < 10} + *
    Selects MBeans that have a {@code FreeSpacePercent} attribute whose + * value is a number less than 10. + * + *
    {@code FreeSpacePercent < 10 and WarningSent = false} + *
    Selects the same MBeans as the previous example, but they must + * also have a boolean attribute {@code WarningSent} whose value + * is false. + * + *
    {@code SpaceUsed > TotalSpace * (2.0 / 3.0)} + *
    Selects MBeans that have {@code SpaceUsed} and {@code TotalSpace} + * attributes where the first is more than two-thirds the second. + * + *
    {@code not (FreeSpacePercent between 10 and 90)} + *
    Selects MBeans that have a {@code FreeSpacePercent} attribute whose + * value is not between 10 and 90, inclusive. + * + *
    {@code FreeSpacePercent not between 10 and 90} + *
    Another way of writing the previous query. + * + *
    {@code Status in ('STOPPED', 'STARTING', 'STARTED')} + *
    Selects MBeans that have a {@code Status} attribute whose value + * is one of those three strings. + * + *
    {@code Message like 'OK: %'} + *
    Selects MBeans that have a {@code Message} attribute whose value + * is a string beginning with {@code "OK: "}. Notice that the + * wildcard characters are SQL's ones. In the query language, + * {@code %} means "any sequence of characters" and {@code _} + * means "any single character". In the rest of the JMX API, these + * correspond to {@code *} and {@code %} respectively. + * + *
    {@code instanceof 'javax.management.NotificationBroadcaster'} + *
    Selects MBeans that are instances of + * {@link javax.management.NotificationBroadcaster}, as reported by + * {@link javax.management.MBeanServer#isInstanceOf MBeanServer.isInstanceOf}. + * + *
    {@code like 'mydomain:*'} + *
    Selects MBeans whose {@link ObjectName}s have the domain {@code mydomain}. + * + *
    + * + *

    The last two examples do not correspond to valid SQL syntax, but all + * the others do.

    + * + *

    The remainder of this description is a formal specification of the + * query language.

    + * + * + *

    Lexical elements

    + * + *

    Keywords such as and, like, and between are not + * case sensitive. You can write between, BETWEEN, or + * BeTwEeN with the same effect.

    + * + *

    On the other hand, attribute names are case sensitive. The + * attribute {@code Name} is not the same as the attribute {@code name}.

    + * + *

    To access an attribute whose name, ignoring case, is the same as one of + * the keywords {@code not}, {@code instanceof}, {@code like}, {@code true}, + * or {@code false}, you can use double quotes, for example {@code "not"}. + * Double quotes can also be used to include non-identifier characters in + * the name of an attribute, for example {@code "attribute-name-with-hyphens"}. + * To include the double quote character in the attribute name, write it + * twice. {@code "foo""bar""baz"} represents the attribute called + * {@code foo"bar"baz}. + * + *

    String constants are written with single quotes like {@code 'this'}. A + * single quote within a string constant must be doubled, for example + * {@code 'can''t'}.

    + * + *

    Integer constants are written as a sequence of decimal digits, + * optionally preceded by a plus or minus sign. An integer constant must be + * a valid input to {@link Long#valueOf(String)}.

    + * + *

    Floating-point constants are written using the Java syntax. A + * floating-point constant must be a valid input to + * {@link Double#valueOf(String)}.

    + * + *

    A boolean constant is either {@code true} or {@code false}, ignoring + * case.

    + * + *

    Spaces cannot appear inside identifiers (unless written with double + * quotes) or keywords or multi-character tokens such as {@code <=}. Spaces can + * appear anywhere else, but are not required except to separate tokens. For + * example, the query {@code a < b and 5 = c} could also be written {@code a + * + * + *

    Grammar

    + * + *
    + *
    query: + *
    andquery [OR query] + * + *
    andquery: + *
    predicate [AND andquery] + * + *
    predicate: + *
    ( query ) |
    + * NOT predicate |
    + * INSTANCEOF stringvalue |
    + * LIKE objectnamepattern |
    + * value predrhs + * + *
    predrhs: + *
    compare value |
    + * [NOT] BETWEEN value AND + * value |
    + * [NOT] IN ( value + * commavalues ) |
    + * [NOT] LIKE stringvalue + * + *
    commavalues: + *
    [ , value commavalues ] + * + *
    compare: + *
    = | < | > | + * <= | >= | <> | != + * + *
    value: + *
    factor [plusorminus + * value] + * + *
    plusorminus: + *
    + | - + * + *
    factor: + *
    term [timesordivide + * factor] + * + *
    timesordivide: + *
    * | / + * + *
    term: + *
    attr | literal | + * ( value ) + * + *
    attr: + *
    name [# name] + * + *
    name: + *
    identifier [.name] + * + *
    identifier: + *
    Java-identifier | double-quoted-identifier + * + *
    literal: + *
    booleanlit | longlit | + * doublelit | stringlit + * + *
    booleanlit: + *
    FALSE | TRUE + * + *
    stringvalue: + *
    stringlit + * + *
    objectnamepattern: + *
    stringlit + * + *
    + * + * + *

    Semantics

    + * + *

    The meaning of the grammar is described in the table below. + * This defines a function q that maps a string to a Java object + * such as a {@link QueryExp} or a {@link ValueExp}.

    + * + * + * + * + *
    String sq(s)
    query1 OR query2 + * {@link Query#or Query.or}(q(query1), q(query2)) + * + *
    query1 AND query2 + * {@link Query#and Query.and}(q(query1), q(query2)) + * + *
    ( queryOrValue ) + * q(queryOrValue) + * + *
    NOT query + * {@link Query#not Query.not}(q(query)) + * + *
    INSTANCEOF stringLiteral + * {@link Query#isInstanceOf Query.isInstanceOf}({@link Query#value(String) Query.value}(q(stringLiteral))) + * + *
    LIKE stringLiteral + * {@link ObjectName#ObjectName(String) new ObjectName}(q(stringLiteral)) + * + *
    value1 = value2 + * {@link Query#eq Query.eq}(q(value1), q(value2)) + * + *
    value1 < value2 + * {@link Query#lt Query.lt}(q(value1), q(value2)) + * + *
    value1 > value2 + * {@link Query#gt Query.gt}(q(value1), q(value2)) + * + *
    value1 <= value2 + * {@link Query#leq Query.leq}(q(value1), q(value2)) + * + *
    value1 >= value2 + * {@link Query#geq Query.geq}(q(value1), q(value2)) + * + *
    value1 <> value2 + * {@link Query#not Query.not}({@link Query#eq Query.eq}(q(value1), q(value2))) + * + *
    value1 != value2 + * {@link Query#not Query.not}({@link Query#eq Query.eq}(q(value1), q(value2))) + * + *
    value1 BETWEEN value2 AND value3 + * {@link Query#between Query.between}(q(value1), + * q(value2), q(value3)) + * + *
    value1 NOT BETWEEN value2 AND value3 + * {@link Query#not Query.not}({@link Query#between Query.between}(q(value1), q(value2), q(value3))) + * + *
    value1 IN ( value2, value3 ) + * {@link Query#in Query.in}(q(value1), + * new ValueExp[] { + * q(value2), q(value3)}) + * + *
    value1 NOT IN ( value2, value3 ) + * {@link Query#not Query.not}({@link Query#in Query.in}(q(value1), + * new ValueExp[] { + * q(value2), q(value3)})) + * + *
    value LIKE stringLiteral + * {@link Query#match Query.match}(q(value), + * translateWildcards(q(stringLiteral))) + * + *
    value NOT LIKE stringLiteral + * {@link Query#not Query.not}({@link Query#match Query.match}(q(value), + * translateWildcards(q(stringLiteral)))) + * + *
    value1 + value2 + * {@link Query#plus Query.plus}(q(value1), q(value2)) + * + *
    value1 - value2 + * {@link Query#minus Query.minus}(q(value1), q(value2)) + * + *
    value1 * value2 + * {@link Query#times Query.times}(q(value1), q(value2)) + * + *
    value1 / value2 + * {@link Query#div Query.div}(q(value1), q(value2)) + * + *
    name + * {@link Query#attr(String) Query.attr}(q(name)) + * + *
    name1#name2 + * {@link Query#attr(String,String) Query.attr}(q(name1), + * q(name2)) + * + *
    FALSE + * {@link Query#value(boolean) Query.value}(false) + * + *
    TRUE + * {@link Query#value(boolean) Query.value}(true) + * + *
    decimalLiteral + * {@link Query#value(long) Query.value}({@link Long#valueOf(String) Long.valueOf}(decimalLiteral)) + * + *
    floatingPointLiteral + * {@link Query#value(double) Query.value}({@link Double#valueOf(String) Double.valueOf}(floatingPointLiteral)) + *
    + * + *

    Here, translateWildcards is a function + * that translates from the SQL notation for wildcards, using {@code %} and + * {@code _}, to the JMX API notation, using {@code *} and {@code ?}. If the + * LIKE string already contains {@code *} or {@code ?}, these characters + * have their literal meanings, and will be quoted in the call to + * {@link Query#match Query.match}.

    + * * @since 1.5 */ public class Query extends Object { @@ -277,16 +604,12 @@ } /** - *

    Returns a new attribute expression.

    - * - *

    Evaluating this expression for a given - * objectName includes performing {@link - * MBeanServer#getAttribute MBeanServer.getAttribute(objectName, - * name)}.

    + *

    Returns a new attribute expression. See {@link AttributeValueExp} + * for a detailed description of the semantics of the expression.

    * * @param name The name of the attribute. * - * @return An attribute expression for the attribute named name. + * @return An attribute expression for the attribute named {@code name}. */ public static AttributeValueExp attr(String name) { return new AttributeValueExp(name); @@ -628,6 +951,63 @@ } /** + *

    Return a string representation of the given query. The string + * returned by this method can be converted back into an equivalent + * query using {@link #fromString fromString}.

    + * + *

    (Two queries are equivalent if they produce the same result in + * all cases. Equivalent queries are not necessarily identical: + * for example the queries {@code Query.lt(Query.attr("A"), Query.attr("B"))} + * and {@code Query.not(Query.ge(Query.attr("A"), Query.attr("B")))} are + * equivalent but not identical.)

    + * + *

    The string returned by this method is only guaranteed to be converted + * back into an equivalent query if {@code query} was constructed, or + * could have been constructed, using the methods of this class. + * If you make a custom query {@code myQuery} by implementing + * {@link QueryExp} yourself then the result of + * {@code Query.toString(myQuery)} is unspecified.

    + * + * @param query the query to convert. If it is null, the result will + * also be null. + * @return the string representation of the query, or null if the + * query is null. + * + * @since 1.7 + */ + public static String toString(QueryExp query) { + if (query == null) + return null; + + if (query instanceof ToQueryString) + return ((ToQueryString) query).toQueryString(); + + return query.toString(); + } + + /** + *

    Produce a query from the given string. The query returned + * by this method can be converted back into a string using + * {@link #toString(QueryExp) toString}. The resultant string will + * not necessarily be equal to {@code s}.

    + * + * @param s the string to convert. + * + * @return a {@code QueryExp} derived by parsing the string, or + * null if the string is null. + * + * @throws IllegalArgumentException if the string is not a valid + * query string. + * + * @since 1.7 + */ + public static QueryExp fromString(String s) { + if (s == null) + return null; + return new QueryParser(s).parseQuery(); + } + + /** * Utility method to escape strings used with * Query.{initial|any|final}SubString() methods. */ diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/javax/management/QueryEval.java --- a/jdk/src/share/classes/javax/management/QueryEval.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/javax/management/QueryEval.java Tue Mar 11 23:37:02 2008 -0700 @@ -38,7 +38,7 @@ * * @since 1.5 */ -public abstract class QueryEval implements Serializable { +public abstract class QueryEval extends ToQueryString implements Serializable { /* Serial version */ private static final long serialVersionUID = 2675899265640874796L; diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/javax/management/QueryExp.java --- a/jdk/src/share/classes/javax/management/QueryExp.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/javax/management/QueryExp.java Tue Mar 11 23:37:02 2008 -0700 @@ -30,9 +30,9 @@ /** - *

    Represents relational constraints that can be used in database - * query "where clauses". Instances of QueryExp are returned by the - * static methods of the {@link Query} class.

    + *

    Represents relational constraints similar to database query "where + * clauses". Instances of QueryExp are returned by the static methods of the + * {@link Query} class.

    * *

    It is possible, but not * recommended, to create custom queries by implementing this @@ -40,6 +40,7 @@ * QueryEval} class than to implement the interface directly, so that * the {@link #setMBeanServer} method works correctly. * + * @see MBeanServer#queryNames MBeanServer.queryNames * @since 1.5 */ public interface QueryExp extends Serializable { diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/javax/management/QueryParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/javax/management/QueryParser.java Tue Mar 11 23:37:02 2008 -0700 @@ -0,0 +1,663 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.management; + +import java.util.ArrayList; +import java.util.Formatter; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +/** + *

    Parser for JMX queries represented in an SQL-like language.

    + */ +/* + * Note that if a query starts with ( then we don't know whether it is + * a predicate or just a value that is parenthesized. So, inefficiently, + * we try to parse a predicate and if that doesn't work we try to parse + * a value. + */ +class QueryParser { + // LEXER STARTS HERE + + private static class Token { + final String string; + Token(String s) { + this.string = s; + } + + @Override + public String toString() { + return string; + } + } + + private static final Token + END = new Token(""), + LPAR = new Token("("), RPAR = new Token(")"), + COMMA = new Token(","), DOT = new Token("."), SHARP = new Token("#"), + PLUS = new Token("+"), MINUS = new Token("-"), + TIMES = new Token("*"), DIVIDE = new Token("/"), + LT = new Token("<"), GT = new Token(">"), + LE = new Token("<="), GE = new Token(">="), + NE = new Token("<>"), EQ = new Token("="), + NOT = new Id("NOT"), INSTANCEOF = new Id("INSTANCEOF"), + FALSE = new Id("FALSE"), TRUE = new Id("TRUE"), + BETWEEN = new Id("BETWEEN"), AND = new Id("AND"), + OR = new Id("OR"), IN = new Id("IN"), + LIKE = new Id("LIKE"), CLASS = new Id("CLASS"); + + // Keywords that can appear where an identifier can appear. + // If an attribute is one of these, then it must be quoted when + // converting a query into a string. + // We use a TreeSet so we can look up case-insensitively. + private static final Set idKeywords = + new TreeSet(String.CASE_INSENSITIVE_ORDER); + static { + for (Token t : new Token[] {NOT, INSTANCEOF, FALSE, TRUE, LIKE, CLASS}) + idKeywords.add(t.string); + }; + + public static String quoteId(String id) { + if (id.contains("\"") || idKeywords.contains(id)) + return '"' + id.replace("\"", "\"\"") + '"'; + else + return id; + } + + private static class Id extends Token { + Id(String id) { + super(id); + } + + // All other tokens use object identity, which means e.g. that one + // occurrence of the string constant 'x' is not the same as another. + // For identifiers, we ignore case when testing for equality so that + // for a keyword such as AND you can also spell it as "And" or "and". + // But we keep the original case of the identifier, so if it's not + // a keyword we will distinguish between the attribute Foo and the + // attribute FOO. + @Override + public boolean equals(Object o) { + return (o instanceof Id && (((Id) o).toString().equalsIgnoreCase(toString()))); + } + } + + private static class QuotedId extends Token { + QuotedId(String id) { + super(id); + } + + @Override + public String toString() { + return '"' + string.replace("\"", "\"\"") + '"'; + } + } + + private static class StringLit extends Token { + StringLit(String s) { + super(s); + } + + @Override + public String toString() { + return '\'' + string.replace("'", "''") + '\''; + } + } + + private static class LongLit extends Token { + long number; + + LongLit(long number) { + super(Long.toString(number)); + this.number = number; + } + } + + private static class DoubleLit extends Token { + double number; + + DoubleLit(double number) { + super(Double.toString(number)); + this.number = number; + } + } + + private static class Tokenizer { + private final String s; + private final int len; + private int i = 0; + + Tokenizer(String s) { + this.s = s; + this.len = s.length(); + } + + private int thisChar() { + if (i == len) + return -1; + return s.codePointAt(i); + } + + private void advance() { + i += Character.charCount(thisChar()); + } + + private int thisCharAdvance() { + int c = thisChar(); + advance(); + return c; + } + + Token nextToken() { + // In this method, c is the character we're looking at, and + // thisChar() is the character after that. Everything must + // preserve these invariants. When we return we then have + // thisChar() being the start of the following token, so + // the next call to nextToken() will begin from there. + int c; + + // Skip space + do { + if (i == len) + return null; + c = thisCharAdvance(); + } while (Character.isWhitespace(c)); + + // Now c is the first character of the token, and tokenI points + // to the character after that. + switch (c) { + case '(': return LPAR; + case ')': return RPAR; + case ',': return COMMA; + case '.': return DOT; + case '#': return SHARP; + case '*': return TIMES; + case '/': return DIVIDE; + case '=': return EQ; + case '-': return MINUS; + case '+': return PLUS; + + case '>': + if (thisChar() == '=') { + advance(); + return GE; + } else + return GT; + + case '<': + c = thisChar(); + switch (c) { + case '=': advance(); return LE; + case '>': advance(); return NE; + default: return LT; + } + + case '!': + if (thisCharAdvance() != '=') + throw new IllegalArgumentException("'!' must be followed by '='"); + return NE; + + case '"': + case '\'': { + int quote = c; + StringBuilder sb = new StringBuilder(); + while (true) { + while ((c = thisChar()) != quote) { + if (c < 0) { + throw new IllegalArgumentException( + "Unterminated string constant"); + } + sb.appendCodePoint(thisCharAdvance()); + } + advance(); + if (thisChar() == quote) { + sb.appendCodePoint(quote); + advance(); + } else + break; + } + if (quote == '\'') + return new StringLit(sb.toString()); + else + return new QuotedId(sb.toString()); + } + } + + // Is it a numeric constant? + if (Character.isDigit(c) || c == '.') { + StringBuilder sb = new StringBuilder(); + int lastc = -1; + while (true) { + sb.appendCodePoint(c); + c = Character.toLowerCase(thisChar()); + if (c == '+' || c == '-') { + if (lastc != 'e') + break; + } else if (!Character.isDigit(c) && c != '.' && c != 'e') + break; + lastc = c; + advance(); + } + String s = sb.toString(); + if (s.indexOf('.') >= 0 || s.indexOf('e') >= 0) { + double d = parseDoubleCheckOverflow(s); + return new DoubleLit(d); + } else { + // Like the Java language, we allow the numeric constant + // x where -x = Long.MIN_VALUE, even though x is not + // representable as a long (it is Long.MAX_VALUE + 1). + // Code in the parser will reject this value if it is + // not the operand of unary minus. + long l = -Long.parseLong("-" + s); + return new LongLit(l); + } + } + + // It must be an identifier. + if (!Character.isJavaIdentifierStart(c)) { + StringBuilder sb = new StringBuilder(); + Formatter f = new Formatter(sb); + f.format("Bad character: %c (%04x)", c, c); + throw new IllegalArgumentException(sb.toString()); + } + + StringBuilder id = new StringBuilder(); + while (true) { // identifier + id.appendCodePoint(c); + c = thisChar(); + if (!Character.isJavaIdentifierPart(c)) + break; + advance(); + } + + return new Id(id.toString()); + } + } + + /* Parse a double as a Java compiler would do it, throwing an exception + * if the input does not fit in a double. We assume that the input + * string is not "Infinity" and does not have a leading sign. + */ + private static double parseDoubleCheckOverflow(String s) { + double d = Double.parseDouble(s); + if (Double.isInfinite(d)) + throw new NumberFormatException("Overflow: " + s); + if (d == 0.0) { // Underflow checking is hard! CR 6604864 + String ss = s; + int e = s.indexOf('e'); // we already forced E to lowercase + if (e > 0) + ss = s.substring(0, e); + ss = ss.replace("0", "").replace(".", ""); + if (!ss.isEmpty()) + throw new NumberFormatException("Underflow: " + s); + } + return d; + } + + // PARSER STARTS HERE + + private final List tokens; + private int tokenI; + // The current token is always tokens[tokenI]. + + QueryParser(String s) { + // Construct the complete list of tokens immediately and append + // a sentinel (END). + tokens = new ArrayList(); + Tokenizer tokenizer = new Tokenizer(s); + Token t; + while ((t = tokenizer.nextToken()) != null) + tokens.add(t); + tokens.add(END); + } + + private Token current() { + return tokens.get(tokenI); + } + + // If the current token is t, then skip it and return true. + // Otherwise, return false. + private boolean skip(Token t) { + if (t.equals(current())) { + tokenI++; + return true; + } + return false; + } + + // If the current token is one of the ones in 'tokens', then skip it + // and return its index in 'tokens'. Otherwise, return -1. + private int skipOne(Token... tokens) { + for (int i = 0; i < tokens.length; i++) { + if (skip(tokens[i])) + return i; + } + return -1; + } + + // If the current token is t, then skip it and return. + // Otherwise throw an exception. + private void expect(Token t) { + if (!skip(t)) + throw new IllegalArgumentException("Expected " + t + ", found " + current()); + } + + private void next() { + tokenI++; + } + + QueryExp parseQuery() { + QueryExp qe = query(); + if (current() != END) + throw new IllegalArgumentException("Junk at end of query: " + current()); + return qe; + } + + // The remainder of this class is a classical recursive-descent parser. + // We only need to violate the recursive-descent scheme in one place, + // where parentheses make the grammar not LL(1). + + private QueryExp query() { + QueryExp lhs = andquery(); + while (skip(OR)) + lhs = Query.or(lhs, andquery()); + return lhs; + } + + private QueryExp andquery() { + QueryExp lhs = predicate(); + while (skip(AND)) + lhs = Query.and(lhs, predicate()); + return lhs; + } + + private QueryExp predicate() { + // Grammar hack. If we see a paren, it might be (query) or + // it might be (value). We try to parse (query), and if that + // fails, we parse (value). For example, if the string is + // "(2+3)*4 < 5" then we will try to parse the query + // "2+3)*4 < 5", which will fail at the ), so we'll back up to + // the paren and let value() handle it. + if (skip(LPAR)) { + int parenIndex = tokenI - 1; + try { + QueryExp qe = query(); + expect(RPAR); + return qe; + } catch (IllegalArgumentException e) { + // OK: try parsing a value + } + tokenI = parenIndex; + } + + if (skip(NOT)) + return Query.not(predicate()); + + if (skip(INSTANCEOF)) + return Query.isInstanceOf(stringvalue()); + + if (skip(LIKE)) { + StringValueExp sve = stringvalue(); + String s = sve.getValue(); + try { + return new ObjectName(s); + } catch (MalformedObjectNameException e) { + throw new IllegalArgumentException( + "Bad ObjectName pattern after LIKE: '" + s + "'", e); + } + } + + ValueExp lhs = value(); + + return predrhs(lhs); + } + + // The order of elements in the following arrays is important. The code + // in predrhs depends on integer indexes. Change with caution. + private static final Token[] relations = { + EQ, LT, GT, LE, GE, NE, + // 0, 1, 2, 3, 4, 5, + }; + private static final Token[] betweenLikeIn = { + BETWEEN, LIKE, IN + // 0, 1, 2, + }; + + private QueryExp predrhs(ValueExp lhs) { + Token start = current(); // for errors + + // Look for < > = etc + int i = skipOne(relations); + if (i >= 0) { + ValueExp rhs = value(); + switch (i) { + case 0: return Query.eq(lhs, rhs); + case 1: return Query.lt(lhs, rhs); + case 2: return Query.gt(lhs, rhs); + case 3: return Query.leq(lhs, rhs); + case 4: return Query.geq(lhs, rhs); + case 5: return Query.not(Query.eq(lhs, rhs)); + // There is no Query.ne so <> is shorthand for the above. + default: + throw new AssertionError(); + } + } + + // Must be BETWEEN LIKE or IN, optionally preceded by NOT + boolean not = skip(NOT); + i = skipOne(betweenLikeIn); + if (i < 0) + throw new IllegalArgumentException("Expected relation at " + start); + + QueryExp q; + switch (i) { + case 0: { // BETWEEN + ValueExp lower = value(); + expect(AND); + ValueExp upper = value(); + q = Query.between(lhs, lower, upper); + break; + } + + case 1: { // LIKE + if (!(lhs instanceof AttributeValueExp)) { + throw new IllegalArgumentException( + "Left-hand side of LIKE must be an attribute"); + } + AttributeValueExp alhs = (AttributeValueExp) lhs; + StringValueExp sve = stringvalue(); + String s = sve.getValue(); + q = Query.match(alhs, patternValueExp(s)); + break; + } + + case 2: { // IN + expect(LPAR); + List values = new ArrayList(); + values.add(value()); + while (skip(COMMA)) + values.add(value()); + expect(RPAR); + q = Query.in(lhs, values.toArray(new ValueExp[values.size()])); + break; + } + + default: + throw new AssertionError(); + } + + if (not) + q = Query.not(q); + + return q; + } + + private ValueExp value() { + ValueExp lhs = factor(); + int i; + while ((i = skipOne(PLUS, MINUS)) >= 0) { + ValueExp rhs = factor(); + if (i == 0) + lhs = Query.plus(lhs, rhs); + else + lhs = Query.minus(lhs, rhs); + } + return lhs; + } + + private ValueExp factor() { + ValueExp lhs = term(); + int i; + while ((i = skipOne(TIMES, DIVIDE)) >= 0) { + ValueExp rhs = term(); + if (i == 0) + lhs = Query.times(lhs, rhs); + else + lhs = Query.div(lhs, rhs); + } + return lhs; + } + + private ValueExp term() { + boolean signed = false; + int sign = +1; + if (skip(PLUS)) + signed = true; + else if (skip(MINUS)) { + signed = true; sign = -1; + } + + Token t = current(); + next(); + + if (t instanceof DoubleLit) + return Query.value(sign * ((DoubleLit) t).number); + if (t instanceof LongLit) { + long n = ((LongLit) t).number; + if (n == Long.MIN_VALUE && sign != -1) + throw new IllegalArgumentException("Illegal positive integer: " + n); + return Query.value(sign * n); + } + if (signed) + throw new IllegalArgumentException("Expected number after + or -"); + + if (t == LPAR) { + ValueExp v = value(); + expect(RPAR); + return v; + } + if (t.equals(FALSE) || t.equals(TRUE)) { + return Query.value(t.equals(TRUE)); + } + if (t.equals(CLASS)) + return Query.classattr(); + + if (t instanceof StringLit) + return Query.value(t.string); // Not toString(), which would requote ' + + // At this point, all that remains is something that will call Query.attr + + if (!(t instanceof Id) && !(t instanceof QuotedId)) + throw new IllegalArgumentException("Unexpected token " + t); + + String name1 = name(t); + + if (skip(SHARP)) { + Token t2 = current(); + next(); + String name2 = name(t2); + return Query.attr(name1, name2); + } + return Query.attr(name1); + } + + // Initially, t is the first token of a supposed name and current() + // is the second. + private String name(Token t) { + StringBuilder sb = new StringBuilder(); + while (true) { + if (!(t instanceof Id) && !(t instanceof QuotedId)) + throw new IllegalArgumentException("Unexpected token " + t); + sb.append(t.string); + if (current() != DOT) + break; + sb.append('.'); + next(); + t = current(); + next(); + } + return sb.toString(); + } + + private StringValueExp stringvalue() { + // Currently the only way to get a StringValueExp when constructing + // a QueryExp is via Query.value(String), so we only recognize + // string literals here. But if we expand queries in the future + // that might no longer be true. + Token t = current(); + next(); + if (!(t instanceof StringLit)) + throw new IllegalArgumentException("Expected string: " + t); + return Query.value(t.string); + } + + // Convert the SQL pattern syntax, using % and _, to the Query.match + // syntax, using * and ?. The tricky part is recognizing \% and + // \_ as literal values, and also not replacing them inside []. + // But Query.match does not recognize \ inside [], which makes our + // job a tad easier. + private StringValueExp patternValueExp(String s) { + int c; + for (int i = 0; i < s.length(); i += Character.charCount(c)) { + c = s.codePointAt(i); + switch (c) { + case '\\': + i++; // i += Character.charCount(c), but we know it's 1! + if (i >= s.length()) + throw new IllegalArgumentException("\\ at end of pattern"); + break; + case '[': + i = s.indexOf(']', i); + if (i < 0) + throw new IllegalArgumentException("[ without ]"); + break; + case '%': + s = s.substring(0, i) + "*" + s.substring(i + 1); + break; + case '_': + s = s.substring(0, i) + "?" + s.substring(i + 1); + break; + case '*': + case '?': + s = s.substring(0, i) + '\\' + (char) c + s.substring(i + 1); + i++; + break; + } + } + return Query.value(s); + } +} diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/javax/management/StringValueExp.java --- a/jdk/src/share/classes/javax/management/StringValueExp.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/javax/management/StringValueExp.java Tue Mar 11 23:37:02 2008 -0700 @@ -73,7 +73,7 @@ * Returns the string representing the object. */ public String toString() { - return "'" + val + "'"; + return "'" + val.replace("'", "''") + "'"; } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/javax/management/ToQueryString.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/javax/management/ToQueryString.java Tue Mar 11 23:37:02 2008 -0700 @@ -0,0 +1,38 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.management; + +/* QueryExp classes can extend this to get non-default treatment for + * Query.toString(q). We're reluctant to change the public toString() + * methods of the classes because people might be parsing them, even + * though that's rather fragile. But Query.toString(q) has no such + * constraint so it can use the new toQueryString() method defined here. + */ +class ToQueryString { + String toQueryString() { + return toString(); + } +} diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/javax/management/monitor/Monitor.java --- a/jdk/src/share/classes/javax/management/monitor/Monitor.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/javax/management/monitor/Monitor.java Tue Mar 11 23:37:02 2008 -0700 @@ -27,13 +27,8 @@ import static com.sun.jmx.defaults.JmxProperties.MONITOR_LOGGER; import com.sun.jmx.mbeanserver.GetPropertyAction; -import com.sun.jmx.remote.util.EnvHelp; -import java.beans.BeanInfo; -import java.beans.Introspector; -import java.beans.PropertyDescriptor; +import com.sun.jmx.mbeanserver.Introspector; import java.io.IOException; -import java.lang.reflect.Array; -import java.lang.reflect.InvocationTargetException; import java.security.AccessControlContext; import java.security.AccessController; import java.security.PrivilegedAction; @@ -64,7 +59,6 @@ import javax.management.ObjectName; import javax.management.ReflectionException; import static javax.management.monitor.MonitorNotification.*; -import javax.management.openmbean.CompositeData; /** * Defines the part common to all monitor MBeans. @@ -876,44 +870,13 @@ if (isComplexTypeAttribute) { Object v = value; for (String attr : remainingAttributes) - v = introspect(object, attr, v); + v = Introspector.elementFromComplex(v, attr); return (Comparable) v; } else { return (Comparable) value; } } - Object introspect(ObjectName object, - String attribute, - Object value) - throws AttributeNotFoundException { - try { - if (value.getClass().isArray() && attribute.equals("length")) { - return Array.getLength(value); - } else if (value instanceof CompositeData) { - return ((CompositeData) value).get(attribute); - } else { - // Java Beans introspection - // - BeanInfo bi = Introspector.getBeanInfo(value.getClass()); - PropertyDescriptor[] pds = bi.getPropertyDescriptors(); - for (PropertyDescriptor pd : pds) - if (pd.getName().equals(attribute)) - return pd.getReadMethod().invoke(value); - throw new AttributeNotFoundException( - "Could not find the getter method for the property " + - attribute + " using the Java Beans introspector"); - } - } catch (InvocationTargetException e) { - throw new IllegalArgumentException(e); - } catch (AttributeNotFoundException e) { - throw e; - } catch (Exception e) { - throw EnvHelp.initCause( - new AttributeNotFoundException(e.getMessage()), e); - } - } - boolean isComparableTypeValid(ObjectName object, String attribute, Comparable value) { diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/javax/management/remote/JMXServiceURL.java --- a/jdk/src/share/classes/javax/management/remote/JMXServiceURL.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/javax/management/remote/JMXServiceURL.java Tue Mar 11 23:37:02 2008 -0700 @@ -30,6 +30,7 @@ import com.sun.jmx.remote.util.ClassLogger; import com.sun.jmx.remote.util.EnvHelp; +import java.beans.ConstructorProperties; import java.io.Serializable; import java.net.InetAddress; import java.net.MalformedURLException; @@ -274,6 +275,7 @@ * is not possible to find the local host name, or if * port is negative. */ + @ConstructorProperties({"protocol", "host", "port", "URLPath"}) public JMXServiceURL(String protocol, String host, int port, String urlPath) throws MalformedURLException { diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/javax/rmi/ssl/SslRMIClientSocketFactory.java --- a/jdk/src/share/classes/javax/rmi/ssl/SslRMIClientSocketFactory.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/javax/rmi/ssl/SslRMIClientSocketFactory.java Tue Mar 11 23:37:02 2008 -0700 @@ -121,7 +121,7 @@ sslSocketFactory.createSocket(host, port); // Set the SSLSocket Enabled Cipher Suites // - final String enabledCipherSuites = (String) + final String enabledCipherSuites = System.getProperty("javax.rmi.ssl.client.enabledCipherSuites"); if (enabledCipherSuites != null) { StringTokenizer st = new StringTokenizer(enabledCipherSuites, ","); @@ -139,7 +139,7 @@ } // Set the SSLSocket Enabled Protocols // - final String enabledProtocols = (String) + final String enabledProtocols = System.getProperty("javax.rmi.ssl.client.enabledProtocols"); if (enabledProtocols != null) { StringTokenizer st = new StringTokenizer(enabledProtocols, ","); diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/javax/rmi/ssl/SslRMIServerSocketFactory.java --- a/jdk/src/share/classes/javax/rmi/ssl/SslRMIServerSocketFactory.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/javax/rmi/ssl/SslRMIServerSocketFactory.java Tue Mar 11 23:37:02 2008 -0700 @@ -165,9 +165,9 @@ // Initialize the configuration parameters. // this.enabledCipherSuites = enabledCipherSuites == null ? - null : (String[]) enabledCipherSuites.clone(); + null : enabledCipherSuites.clone(); this.enabledProtocols = enabledProtocols == null ? - null : (String[]) enabledProtocols.clone(); + null : enabledProtocols.clone(); this.needClientAuth = needClientAuth; // Force the initialization of the default at construction time, @@ -196,13 +196,11 @@ // if (this.enabledCipherSuites != null) { sslSocket.setEnabledCipherSuites(this.enabledCipherSuites); - enabledCipherSuitesList = - Arrays.asList((String[]) this.enabledCipherSuites); + enabledCipherSuitesList = Arrays.asList(this.enabledCipherSuites); } if (this.enabledProtocols != null) { sslSocket.setEnabledProtocols(this.enabledProtocols); - enabledProtocolsList = - Arrays.asList((String[]) this.enabledProtocols); + enabledProtocolsList = Arrays.asList(this.enabledProtocols); } } @@ -218,7 +216,7 @@ */ public final String[] getEnabledCipherSuites() { return enabledCipherSuites == null ? - null : (String[]) enabledCipherSuites.clone(); + null : enabledCipherSuites.clone(); } /** @@ -234,7 +232,7 @@ */ public final String[] getEnabledProtocols() { return enabledProtocols == null ? - null : (String[]) enabledProtocols.clone(); + null : enabledProtocols.clone(); } /** @@ -315,8 +313,8 @@ (enabledCipherSuites != null && that.enabledCipherSuites == null)) return false; if (enabledCipherSuites != null && that.enabledCipherSuites != null) { - List thatEnabledCipherSuitesList = - Arrays.asList((String[]) that.enabledCipherSuites); + List thatEnabledCipherSuitesList = + Arrays.asList(that.enabledCipherSuites); if (!enabledCipherSuitesList.equals(thatEnabledCipherSuitesList)) return false; } @@ -327,8 +325,8 @@ (enabledProtocols != null && that.enabledProtocols == null)) return false; if (enabledProtocols != null && that.enabledProtocols != null) { - List thatEnabledProtocolsList = - Arrays.asList((String[]) that.enabledProtocols); + List thatEnabledProtocolsList = + Arrays.asList(that.enabledProtocols); if (!enabledProtocolsList.equals(thatEnabledProtocolsList)) return false; } @@ -374,7 +372,7 @@ private final String[] enabledCipherSuites; private final String[] enabledProtocols; private final boolean needClientAuth; - private List enabledCipherSuitesList; - private List enabledProtocolsList; + private List enabledCipherSuitesList; + private List enabledProtocolsList; private SSLContext context; } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/javax/security/auth/kerberos/KerberosTicket.java --- a/jdk/src/share/classes/javax/security/auth/kerberos/KerberosTicket.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/javax/security/auth/kerberos/KerberosTicket.java Tue Mar 11 23:37:02 2008 -0700 @@ -276,7 +276,7 @@ if (flags != null) { if (flags.length >= NUM_FLAGS) - this.flags = (boolean[]) flags.clone(); + this.flags = flags.clone(); else { this.flags = new boolean[NUM_FLAGS]; // Fill in whatever we have @@ -304,7 +304,7 @@ this.endTime = endTime; if (clientAddresses != null) - this.clientAddresses = (InetAddress[]) clientAddresses.clone(); + this.clientAddresses = clientAddresses.clone(); } /** @@ -430,7 +430,7 @@ * @return the flags associated with this ticket. */ public final boolean[] getFlags() { - return (flags == null? null: (boolean[]) flags.clone()); + return (flags == null? null: flags.clone()); } /** @@ -479,8 +479,7 @@ * provided. */ public final java.net.InetAddress[] getClientAddresses() { - return (clientAddresses == null? - null: (InetAddress[]) clientAddresses.clone()); + return (clientAddresses == null) ? null: clientAddresses.clone(); } /** @@ -491,7 +490,7 @@ public final byte[] getEncoded() { if (destroyed) throw new IllegalStateException("This ticket is no longer valid"); - return (byte[]) asn1Encoding.clone(); + return asn1Encoding.clone(); } /** Determines if this ticket is still current. */ diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/javax/security/auth/kerberos/KeyImpl.java --- a/jdk/src/share/classes/javax/security/auth/kerberos/KeyImpl.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/javax/security/auth/kerberos/KeyImpl.java Tue Mar 11 23:37:02 2008 -0700 @@ -66,7 +66,7 @@ */ public KeyImpl(byte[] keyBytes, int keyType) { - this.keyBytes = (byte[]) keyBytes.clone(); + this.keyBytes = keyBytes.clone(); this.keyType = keyType; } @@ -151,7 +151,7 @@ public final byte[] getEncoded() { if (destroyed) throw new IllegalStateException("This key is no longer valid"); - return (byte[])keyBytes.clone(); + return keyBytes.clone(); } public void destroy() throws DestroyFailedException { diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/management/ConnectorAddressLink.java --- a/jdk/src/share/classes/sun/management/ConnectorAddressLink.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/management/ConnectorAddressLink.java Tue Mar 11 23:37:02 2008 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2004-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,12 +25,13 @@ package sun.management; +import java.io.IOException; import java.nio.ByteBuffer; -import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; import java.util.List; -import java.util.Iterator; -import java.util.Set; -import java.io.IOException; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; import sun.misc.Perf; import sun.management.counter.Units; @@ -46,36 +47,67 @@ public class ConnectorAddressLink { private static final String CONNECTOR_ADDRESS_COUNTER = - "sun.management.JMXConnectorServer.address"; + "sun.management.JMXConnectorServer.address"; + + /* + * The format of the jvmstat counters representing the properties of + * a given out-of-the-box JMX remote connector will be as follows: + * + * sun.management.JMXConnectorServer..= + * + * where: + * + * counter = index computed by this class which uniquely identifies + * an out-of-the-box JMX remote connector running in this + * Java virtual machine. + * key/value = a given key/value pair in the map supplied to the + * exportRemote() method. + * + * For example, + * + * sun.management.JMXConnectorServer.0.remoteAddress=service:jmx:rmi:///jndi/rmi://myhost:5000/jmxrmi + * sun.management.JMXConnectorServer.0.authenticate=false + * sun.management.JMXConnectorServer.0.ssl=false + * sun.management.JMXConnectorServer.0.sslRegistry=false + * sun.management.JMXConnectorServer.0.sslNeedClientAuth=false + */ + private static final String REMOTE_CONNECTOR_COUNTER_PREFIX = + "sun.management.JMXConnectorServer."; + + /* + * JMX remote connector counter (it will be incremented every + * time a new out-of-the-box JMX remote connector is created). + */ + private static AtomicInteger counter = new AtomicInteger(); /** * Exports the specified connector address to the instrumentation buffer * so that it can be read by this or other Java virtual machines running * on the same system. * - * @param address The connector address. + * @param address The connector address. */ public static void export(String address) { if (address == null || address.length() == 0) { throw new IllegalArgumentException("address not specified"); } Perf perf = Perf.getPerf(); - perf.createString(CONNECTOR_ADDRESS_COUNTER, 1, Units.STRING.intValue(), address); + perf.createString( + CONNECTOR_ADDRESS_COUNTER, 1, Units.STRING.intValue(), address); } /** * Imports the connector address from the instrument buffer * of the specified Java virtual machine. * - * @param vmid an identifier that uniquely identifies a local - * Java virtual machine, or 0 to indicate - * the current Java virtual machine. + * @param vmid an identifier that uniquely identifies a local Java virtual + * machine, or 0 to indicate the current Java virtual machine. * - * @return the value of the connector address, or null - * if the target VM has not exported a connector address. + * @return the value of the connector address, or null if the + * target VM has not exported a connector address. * - * @throws IOException An I/O error occurred while trying to acquire - * the instrumentation buffer. + * @throws IOException An I/O error occurred while trying to acquire the + * instrumentation buffer. */ public static String importFrom(int vmid) throws IOException { Perf perf = Perf.getPerf(); @@ -85,14 +117,65 @@ } catch (IllegalArgumentException iae) { throw new IOException(iae.getMessage()); } - List counters = (new PerfInstrumentation(bb)).findByPattern(CONNECTOR_ADDRESS_COUNTER); + List counters = + new PerfInstrumentation(bb).findByPattern(CONNECTOR_ADDRESS_COUNTER); Iterator i = counters.iterator(); if (i.hasNext()) { - Counter c = (Counter)i.next(); - return (String)c.getValue(); + Counter c = (Counter) i.next(); + return (String) c.getValue(); } else { return null; } } + /** + * Exports the specified remote connector address and associated + * configuration properties to the instrumentation buffer so that + * it can be read by this or other Java virtual machines running + * on the same system. + * + * @param properties The remote connector address properties. + */ + public static void exportRemote(Map properties) { + final int index = counter.getAndIncrement(); + Perf perf = Perf.getPerf(); + for (Map.Entry entry : properties.entrySet()) { + perf.createString(REMOTE_CONNECTOR_COUNTER_PREFIX + index + "." + + entry.getKey(), 1, Units.STRING.intValue(), entry.getValue()); + } + } + + /** + * Imports the remote connector address and associated + * configuration properties from the instrument buffer + * of the specified Java virtual machine. + * + * @param vmid an identifier that uniquely identifies a local Java virtual + * machine, or 0 to indicate the current Java virtual machine. + * + * @return a map containing the remote connector's properties, or an empty + * map if the target VM has not exported the remote connector's properties. + * + * @throws IOException An I/O error occurred while trying to acquire the + * instrumentation buffer. + */ + public static Map importRemoteFrom(int vmid) throws IOException { + Perf perf = Perf.getPerf(); + ByteBuffer bb; + try { + bb = perf.attach(vmid, "r"); + } catch (IllegalArgumentException iae) { + throw new IOException(iae.getMessage()); + } + List counters = new PerfInstrumentation(bb).getAllCounters(); + Map properties = new HashMap(); + for (Object c : counters) { + String name = ((Counter) c).getName(); + if (name.startsWith(REMOTE_CONNECTOR_COUNTER_PREFIX) && + !name.equals(CONNECTOR_ADDRESS_COUNTER)) { + properties.put(name, ((Counter) c).getValue().toString()); + } + } + return properties; + } } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java --- a/jdk/src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java Tue Mar 11 23:37:02 2008 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,7 @@ import java.rmi.Remote; import java.rmi.RemoteException; import java.rmi.registry.Registry; +import java.rmi.server.RemoteObject; import java.rmi.server.RMIClientSocketFactory; import java.rmi.server.RMIServerSocketFactory; import java.rmi.server.UnicastRemoteObject; @@ -70,12 +71,14 @@ import javax.security.auth.Subject; +import sun.rmi.server.UnicastRef; import sun.rmi.server.UnicastServerRef; import sun.rmi.server.UnicastServerRef2; import sun.management.Agent; import sun.management.AgentConfigurationError; import static sun.management.AgentConfigurationError.*; +import sun.management.ConnectorAddressLink; import sun.management.FileSystem; import sun.management.snmp.util.MibLogger; @@ -92,20 +95,22 @@ * Default values for JMX configuration properties. **/ public static interface DefaultValues { - public static final String PORT="0"; - public static final String CONFIG_FILE_NAME="management.properties"; - public static final String USE_SSL="true"; - public static final String USE_REGISTRY_SSL="false"; - public static final String USE_AUTHENTICATION="true"; - public static final String PASSWORD_FILE_NAME="jmxremote.password"; - public static final String ACCESS_FILE_NAME="jmxremote.access"; - public static final String SSL_NEED_CLIENT_AUTH="false"; + + public static final String PORT = "0"; + public static final String CONFIG_FILE_NAME = "management.properties"; + public static final String USE_SSL = "true"; + public static final String USE_REGISTRY_SSL = "false"; + public static final String USE_AUTHENTICATION = "true"; + public static final String PASSWORD_FILE_NAME = "jmxremote.password"; + public static final String ACCESS_FILE_NAME = "jmxremote.access"; + public static final String SSL_NEED_CLIENT_AUTH = "false"; } /** * Names of JMX configuration properties. **/ public static interface PropertyNames { + public static final String PORT = "com.sun.management.jmxremote.port"; public static final String CONFIG_FILE_NAME = @@ -133,6 +138,21 @@ } /** + * JMXConnectorServer associated data. + */ + private static class JMXConnectorServerData { + + public JMXConnectorServerData( + JMXConnectorServer jmxConnectorServer, + JMXServiceURL jmxRemoteURL) { + this.jmxConnectorServer = jmxConnectorServer; + this.jmxRemoteURL = jmxRemoteURL; + } + JMXConnectorServer jmxConnectorServer; + JMXServiceURL jmxRemoteURL; + } + + /** *

    Prevents our RMI server objects from keeping the JVM alive.

    * *

    We use a private interface in Sun's JMX Remote API implementation @@ -151,6 +171,7 @@ * works). Hence the somewhat misleading name of this class.

    */ private static class PermanentExporter implements RMIExporter { + public Remote exportObject(Remote obj, int port, RMIClientSocketFactory csf, @@ -158,24 +179,25 @@ throws RemoteException { synchronized (this) { - if (firstExported == null) + if (firstExported == null) { firstExported = obj; + } } final UnicastServerRef ref; - if (csf == null && ssf == null) + if (csf == null && ssf == null) { ref = new UnicastServerRef(port); - else + } else { ref = new UnicastServerRef2(port, csf, ssf); + } return ref.exportObject(obj, null, true); } // Nothing special to be done for this case public boolean unexportObject(Remote obj, boolean force) - throws NoSuchObjectException { + throws NoSuchObjectException { return UnicastRemoteObject.unexportObject(obj, force); } - Remote firstExported; } @@ -202,19 +224,21 @@ } private void checkAccessFileEntries(Subject subject) { - if (subject == null) + if (subject == null) { throw new SecurityException( "Access denied! No matching entries found in " + "the access file [" + accessFile + "] as the " + "authenticated Subject is null"); + } final Set principals = subject.getPrincipals(); - for (Iterator i = principals.iterator(); i.hasNext(); ) { + for (Iterator i = principals.iterator(); i.hasNext();) { final Principal p = (Principal) i.next(); - if (properties.containsKey(p.getName())) + if (properties.containsKey(p.getName())) { return; + } } final Set principalsStr = new HashSet(); - for (Iterator i = principals.iterator(); i.hasNext(); ) { + for (Iterator i = principals.iterator(); i.hasNext();) { final Principal p = (Principal) i.next(); principalsStr.add(p.getName()); } @@ -225,16 +249,16 @@ } private static Properties propertiesFromFile(String fname) - throws IOException { + throws IOException { Properties p = new Properties(); - if (fname == null) + if (fname == null) { return p; + } FileInputStream fin = new FileInputStream(fname); p.load(fin); fin.close(); return p; } - private final Map environment; private final Properties properties; private final String accessFile; @@ -251,22 +275,23 @@ // Load a new management properties final Properties props = Agent.loadManagementProperties(); - if (props == null) return null; + if (props == null) { + return null; + } final String portStr = props.getProperty(PropertyNames.PORT); // System.out.println("initializing: {port=" + portStr + ", // properties="+props+"}"); - return initialize(portStr,props); + return initialize(portStr, props); } /** * Initializes and starts a JMX Connector Server for remote * monitoring and management. **/ - public static synchronized - JMXConnectorServer initialize(String portStr, Properties props) { + public static synchronized JMXConnectorServer initialize(String portStr, Properties props) { // Get port number final int port; @@ -280,21 +305,21 @@ } // Do we use authentication? - final String useAuthenticationStr = + final String useAuthenticationStr = props.getProperty(PropertyNames.USE_AUTHENTICATION, DefaultValues.USE_AUTHENTICATION); final boolean useAuthentication = Boolean.valueOf(useAuthenticationStr).booleanValue(); // Do we use SSL? - final String useSslStr = + final String useSslStr = props.getProperty(PropertyNames.USE_SSL, DefaultValues.USE_SSL); final boolean useSsl = Boolean.valueOf(useSslStr).booleanValue(); // Do we use RMI Registry SSL? - final String useRegistrySslStr = + final String useRegistrySslStr = props.getProperty(PropertyNames.USE_REGISTRY_SSL, DefaultValues.USE_REGISTRY_SSL); final boolean useRegistrySsl = @@ -307,7 +332,7 @@ StringTokenizer st = new StringTokenizer(enabledCipherSuites, ","); int tokens = st.countTokens(); enabledCipherSuitesList = new String[tokens]; - for (int i = 0 ; i < tokens; i++) { + for (int i = 0; i < tokens; i++) { enabledCipherSuitesList[i] = st.nextToken(); } } @@ -319,12 +344,12 @@ StringTokenizer st = new StringTokenizer(enabledProtocols, ","); int tokens = st.countTokens(); enabledProtocolsList = new String[tokens]; - for (int i = 0 ; i < tokens; i++) { + for (int i = 0; i < tokens; i++) { enabledProtocolsList[i] = st.nextToken(); } } - final String sslNeedClientAuthStr = + final String sslNeedClientAuthStr = props.getProperty(PropertyNames.SSL_NEED_CLIENT_AUTH, DefaultValues.SSL_NEED_CLIENT_AUTH); final boolean sslNeedClientAuth = @@ -374,39 +399,49 @@ sslNeedClientAuth + "\n\t" + PropertyNames.USE_AUTHENTICATION + "=" + useAuthentication + - (useAuthentication ? - (loginConfigName == null ? - ("\n\t" + PropertyNames.PASSWORD_FILE_NAME + "=" + - passwordFileName) : - ("\n\t" + PropertyNames.LOGIN_CONFIG_NAME + "=" + + (useAuthentication ? (loginConfigName == null ? ("\n\t" + PropertyNames.PASSWORD_FILE_NAME + "=" + + passwordFileName) : ("\n\t" + PropertyNames.LOGIN_CONFIG_NAME + "=" + loginConfigName)) : "\n\t" + Agent.getText("jmxremote.ConnectorBootstrap.initialize.noAuthentication")) + - (useAuthentication ? - ("\n\t" + PropertyNames.ACCESS_FILE_NAME + "=" + + (useAuthentication ? ("\n\t" + PropertyNames.ACCESS_FILE_NAME + "=" + accessFileName) : "") + ""); } final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); JMXConnectorServer cs = null; + JMXServiceURL url = null; try { - cs = exportMBeanServer(mbs, port, useSsl, useRegistrySsl, + final JMXConnectorServerData data = exportMBeanServer( + mbs, port, useSsl, useRegistrySsl, sslConfigFileName, enabledCipherSuitesList, enabledProtocolsList, sslNeedClientAuth, useAuthentication, loginConfigName, passwordFileName, accessFileName); - - final JMXServiceURL url = cs.getAddress(); + cs = data.jmxConnectorServer; + url = data.jmxRemoteURL; log.config("initialize", Agent.getText("jmxremote.ConnectorBootstrap.initialize.ready", - new JMXServiceURL(url.getProtocol(), - url.getHost(), - url.getPort(), - "/jndi/rmi://"+url.getHost()+":"+port+"/"+ - "jmxrmi").toString())); + url.toString())); } catch (Exception e) { throw new AgentConfigurationError(AGENT_EXCEPTION, e, e.toString()); } + try { + // Export remote connector address and associated configuration + // properties to the instrumentation buffer. + Map properties = new HashMap(); + properties.put("remoteAddress", url.toString()); + properties.put("authenticate", useAuthenticationStr); + properties.put("ssl", useSslStr); + properties.put("sslRegistry", useRegistrySslStr); + properties.put("sslNeedClientAuth", sslNeedClientAuthStr); + ConnectorAddressLink.exportRemote(properties); + } catch (Exception e) { + // Remote connector server started but unable to export remote + // connector address and associated configuration properties to + // the instrumentation buffer - non-fatal error. + log.debug("initialize", e); + } return cs; } @@ -452,7 +487,7 @@ } private static void checkPasswordFile(String passwordFileName) { - if (passwordFileName == null || passwordFileName.length()==0) { + if (passwordFileName == null || passwordFileName.length() == 0) { throw new AgentConfigurationError(PASSWORD_FILE_NOT_SET); } File file = new File(passwordFileName); @@ -468,9 +503,9 @@ try { if (fs.supportsFileSecurity(file)) { if (!fs.isAccessUserOnly(file)) { - final String msg=Agent.getText("jmxremote.ConnectorBootstrap.initialize.password.readonly", + final String msg = Agent.getText("jmxremote.ConnectorBootstrap.initialize.password.readonly", passwordFileName); - log.config("initialize",msg); + log.config("initialize", msg); throw new AgentConfigurationError(PASSWORD_FILE_ACCESS_NOT_RESTRICTED, passwordFileName); } @@ -482,7 +517,7 @@ } private static void checkAccessFile(String accessFileName) { - if (accessFileName == null || accessFileName.length()==0) { + if (accessFileName == null || accessFileName.length() == 0) { throw new AgentConfigurationError(ACCESS_FILE_NOT_SET); } File file = new File(accessFileName); @@ -619,7 +654,7 @@ } } - private static JMXConnectorServer exportMBeanServer( + private static JMXConnectorServerData exportMBeanServer( MBeanServer mbs, int port, boolean useSsl, @@ -697,24 +732,30 @@ } final Registry registry; - if (useRegistrySsl) + if (useRegistrySsl) { registry = new SingleEntryRegistry(port, csf, ssf, "jmxrmi", exporter.firstExported); - else + } else { registry = new SingleEntryRegistry(port, "jmxrmi", exporter.firstExported); + } + + JMXServiceURL remoteURL = new JMXServiceURL( + "service:jmx:rmi:///jndi/rmi://" + url.getHost() + ":" + + ((UnicastRef) ((RemoteObject) registry).getRef()).getLiveRef().getPort() + + "/jmxrmi"); /* Our exporter remembers the first object it was asked to - export, which will be an RMIServerImpl appropriate for - publication in our special registry. We could - alternatively have constructed the RMIServerImpl explicitly - and then constructed an RMIConnectorServer passing it as a - parameter, but that's quite a bit more verbose and pulls in - lots of knowledge of the RMI connector. */ + export, which will be an RMIServerImpl appropriate for + publication in our special registry. We could + alternatively have constructed the RMIServerImpl explicitly + and then constructed an RMIConnectorServer passing it as a + parameter, but that's quite a bit more verbose and pulls in + lots of knowledge of the RMI connector. */ - return connServer; + return new JMXConnectorServerData(connServer, remoteURL); } /** @@ -726,5 +767,4 @@ // XXX Revisit: should probably clone this MibLogger.... private static final MibLogger log = new MibLogger(ConnectorBootstrap.class); - } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/management/snmp/jvminstr/JvmMemPoolEntryImpl.java --- a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmMemPoolEntryImpl.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmMemPoolEntryImpl.java Tue Mar 11 23:37:02 2008 -0700 @@ -26,7 +26,6 @@ // java imports // -import java.io.Serializable; import java.util.Map; // jmx imports @@ -36,9 +35,7 @@ // jdmk imports // -import com.sun.jmx.snmp.agent.SnmpMib; -import java.lang.management.ManagementFactory; import java.lang.management.MemoryUsage; import java.lang.management.MemoryType; import java.lang.management.MemoryPoolMXBean; @@ -73,7 +70,9 @@ "jvmMemPoolEntry.getCollectionUsage"; final static MemoryUsage ZEROS = new MemoryUsage(0,0,0,0); - + final String entryMemoryTag; + final String entryPeakMemoryTag; + final String entryCollectMemoryTag; MemoryUsage getMemoryUsage() { try { @@ -81,17 +80,17 @@ if (m != null) { final MemoryUsage cached = (MemoryUsage) - m.get(memoryTag); + m.get(entryMemoryTag); if (cached != null) { - log.debug("getMemoryUsage", - "jvmMemPoolEntry.getUsage found in cache."); + log.debug("getMemoryUsage",entryMemoryTag+ + " found in cache."); return cached; } MemoryUsage u = pool.getUsage(); if (u == null) u = ZEROS; - m.put(memoryTag,u); + m.put(entryMemoryTag,u); return u; } // Should never come here. @@ -113,18 +112,18 @@ if (m != null) { final MemoryUsage cached = (MemoryUsage) - m.get(peakMemoryTag); + m.get(entryPeakMemoryTag); if (cached != null) { if (log.isDebugOn()) log.debug("getPeakMemoryUsage", - peakMemoryTag + " found in cache."); + entryPeakMemoryTag + " found in cache."); return cached; } MemoryUsage u = pool.getPeakUsage(); if (u == null) u = ZEROS; - m.put(peakMemoryTag,u); + m.put(entryPeakMemoryTag,u); return u; } // Should never come here. @@ -146,18 +145,18 @@ if (m != null) { final MemoryUsage cached = (MemoryUsage) - m.get(collectMemoryTag); + m.get(entryCollectMemoryTag); if (cached != null) { if (log.isDebugOn()) log.debug("getCollectMemoryUsage", - collectMemoryTag + " found in cache."); + entryCollectMemoryTag + " found in cache."); return cached; } MemoryUsage u = pool.getCollectionUsage(); if (u == null) u = ZEROS; - m.put(collectMemoryTag,u); + m.put(entryCollectMemoryTag,u); return u; } // Should never come here. @@ -179,9 +178,12 @@ /** * Constructor for the "JvmMemPoolEntry" group. */ - public JvmMemPoolEntryImpl(MemoryPoolMXBean mp, int index) { + public JvmMemPoolEntryImpl(MemoryPoolMXBean mp, final int index) { this.pool=mp; this.jvmMemPoolIndex = index; + this.entryMemoryTag = memoryTag + "." + index; + this.entryPeakMemoryTag = peakMemoryTag + "." + index; + this.entryCollectMemoryTag = collectMemoryTag + "." + index; } /** diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/misc/ClassFileTransformer.java --- a/jdk/src/share/classes/sun/misc/ClassFileTransformer.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/misc/ClassFileTransformer.java Tue Mar 11 23:37:02 2008 -0700 @@ -46,8 +46,10 @@ { // Singleton of ClassFileTransformer // - private static ArrayList transformerList = new ArrayList(); - private static Object[] transformers = new Object[0]; + private static ArrayList transformerList + = new ArrayList(); + private static ClassFileTransformer[] transformers + = new ClassFileTransformer[0]; /** * Add the class file transformer object. @@ -59,7 +61,7 @@ synchronized(transformerList) { transformerList.add(t); - transformers = transformerList.toArray(); + transformers = transformerList.toArray(new ClassFileTransformer[0]); } } @@ -68,7 +70,7 @@ * * @return ClassFileTransformer object array */ - public static Object[] getTransformers() + public static ClassFileTransformer[] getTransformers() { // transformers is not intended to be changed frequently, // so it is okay to not put synchronized block here diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/misc/Cleaner.java --- a/jdk/src/share/classes/sun/misc/Cleaner.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/misc/Cleaner.java Tue Mar 11 23:37:02 2008 -0700 @@ -141,8 +141,8 @@ try { thunk.run(); } catch (final Throwable x) { - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { if (System.err != null) new Error("Cleaner terminated abnormally", x) .printStackTrace(); diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/misc/ExtensionDependency.java --- a/jdk/src/share/classes/sun/misc/ExtensionDependency.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/misc/ExtensionDependency.java Tue Mar 11 23:37:02 2008 -0700 @@ -284,10 +284,9 @@ // Load the jar file ... Manifest man; try { - man = (Manifest) AccessController.doPrivileged - ( - new PrivilegedExceptionAction() { - public Object run() + man = AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public Manifest run() throws IOException, FileNotFoundException { if (!file.exists()) throw new FileNotFoundException(file.getName()); @@ -391,9 +390,9 @@ final String extName = extensionName; final String[] fileExt = {".jar", ".zip"}; - return (File) AccessController.doPrivileged - (new PrivilegedAction() { - public Object run() { + return AccessController.doPrivileged( + new PrivilegedAction() { + public File run() { try { File fExtension; File[] dirs = getExtDirs(); @@ -460,7 +459,7 @@ * @return the list of files installed in all the directories */ private static File[] getExtFiles(File[] dirs) throws IOException { - Vector urls = new Vector(); + Vector urls = new Vector(); for (int i = 0; i < dirs.length; i++) { String[] files = dirs[i].list(new JarFilter()); if (files != null) { @@ -484,16 +483,15 @@ *

    */ private File[] getInstalledExtensions() throws IOException { - return (File[]) AccessController.doPrivileged - ( - new PrivilegedAction() { - public Object run() { + return AccessController.doPrivileged( + new PrivilegedAction() { + public File[] run() { try { return getExtFiles(getExtDirs()); } catch(IOException e) { debug("Cannot get list of installed extensions"); debugException(e); - return new URL[0]; + return new File[0]; } } }); diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/misc/GC.java --- a/jdk/src/share/classes/sun/misc/GC.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/misc/GC.java Tue Mar 11 23:37:02 2008 -0700 @@ -128,8 +128,8 @@ /* Create a new daemon thread in the root thread group */ public static void create() { - PrivilegedAction pa = new PrivilegedAction() { - public Object run() { + PrivilegedAction pa = new PrivilegedAction() { + public Void run() { ThreadGroup tg = Thread.currentThread().getThreadGroup(); for (ThreadGroup tgn = tg; tgn != null; @@ -170,13 +170,14 @@ * method. Given a request, the only interesting operation is that of * cancellation. */ - public static class LatencyRequest implements Comparable { + public static class LatencyRequest + implements Comparable { /* Instance counter, used to generate unique identifers */ private static long counter = 0; /* Sorted set of active latency requests */ - private static SortedSet requests = null; + private static SortedSet requests = null; /* Examine the request set and reset the latency target if necessary. * Must be invoked while holding the lock. @@ -187,7 +188,7 @@ setLatencyTarget(NO_TARGET); } } else { - LatencyRequest r = (LatencyRequest)requests.first(); + LatencyRequest r = requests.first(); if (r.latency != latencyTarget) { setLatencyTarget(r.latency); } @@ -211,7 +212,7 @@ synchronized (lock) { this.id = ++counter; if (requests == null) { - requests = new TreeSet(); + requests = new TreeSet(); } requests.add(this); adjustLatencyIfNeeded(); @@ -240,8 +241,7 @@ } } - public int compareTo(Object o) { - LatencyRequest r = (LatencyRequest)o; + public int compareTo(LatencyRequest r) { long d = this.latency - r.latency; if (d == 0) d = this.id - r.id; return (d < 0) ? -1 : ((d > 0) ? +1 : 0); diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/misc/JavaIOFileDescriptorAccess.java --- a/jdk/src/share/classes/sun/misc/JavaIOFileDescriptorAccess.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/misc/JavaIOFileDescriptorAccess.java Tue Mar 11 23:37:02 2008 -0700 @@ -33,4 +33,8 @@ public interface JavaIOFileDescriptorAccess { public void set(FileDescriptor obj, int fd); public int get(FileDescriptor fd); + + // Only valid on Windows + public void setHandle(FileDescriptor obj, long handle); + public long getHandle(FileDescriptor obj); } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/misc/Launcher.java --- a/jdk/src/share/classes/sun/misc/Launcher.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/misc/Launcher.java Tue Mar 11 23:37:02 2008 -0700 @@ -135,9 +135,9 @@ // aa synthesized ACC via a call to the private method // ExtClassLoader.getContext(). - return (ExtClassLoader) AccessController.doPrivileged( - new PrivilegedExceptionAction() { - public Object run() throws IOException { + return AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public ExtClassLoader run() throws IOException { int len = dirs.length; for (int i = 0; i < len; i++) { MetaIndex.registerDirectory(dirs[i]); @@ -180,7 +180,7 @@ } private static URL[] getExtURLs(File[] dirs) throws IOException { - Vector urls = new Vector(); + Vector urls = new Vector(); for (int i = 0; i < dirs.length; i++) { String[] files = dirs[i].list(); if (files != null) { @@ -261,9 +261,9 @@ // when loading classes. Specifically it prevent // accessClassInPackage.sun.* grants from being honored. // - return (AppClassLoader) - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + return AccessController.doPrivileged( + new PrivilegedAction() { + public AppClassLoader run() { URL[] urls = (s == null) ? new URL[0] : pathToURLs(path); return new AppClassLoader(urls, extcl); @@ -348,12 +348,12 @@ URL[] urls; if (prop != null) { final String path = prop; - urls = (URL[])AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { + urls = AccessController.doPrivileged( + new PrivilegedAction() { + public URL[] run() { File[] classPath = getClassPath(path); int len = classPath.length; - Set seenDirs = new HashSet(); + Set seenDirs = new HashSet(); for (int i = 0; i < len; i++) { File curEntry = classPath[i]; // Negative test used to properly handle @@ -509,8 +509,8 @@ perms.add(new java.util.PropertyPermission("java.*", SecurityConstants.PROPERTY_READ_ACTION)); - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { for (int i=0; i < path.length; i++) { File f = path[i]; String path; @@ -553,7 +553,7 @@ return perms.implies(permission); } - public java.util.Enumeration elements() { + public java.util.Enumeration elements() { if (perms == null) init(); synchronized (perms) { diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/misc/PerformanceLogger.java --- a/jdk/src/share/classes/sun/misc/PerformanceLogger.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/misc/PerformanceLogger.java Tue Mar 11 23:37:02 2008 -0700 @@ -78,7 +78,7 @@ private static boolean perfLoggingOn = false; private static boolean useNanoTime = false; - private static Vector times; + private static Vector times; private static String logFileName = null; private static Writer logWriter = null; @@ -104,8 +104,8 @@ if (logFileName != null) { if (logWriter == null) { java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { + new java.security.PrivilegedAction() { + public Void run() { try { File logFile = new File(logFileName); logFile.createNewFile(); @@ -124,7 +124,7 @@ logWriter = new OutputStreamWriter(System.out); } } - times = new Vector(10); + times = new Vector(10); // Reserve predefined slots for (int i = 0; i <= LAST_RESERVED; ++i) { times.add(new TimeData("Time " + i + " not set", 0)); @@ -207,7 +207,7 @@ */ public static long getStartTime() { if (loggingEnabled()) { - return ((TimeData)times.get(START_INDEX)).getTime(); + return times.get(START_INDEX).getTime(); } else { return 0; } @@ -253,7 +253,7 @@ */ public static long getTimeAtIndex(int index) { if (loggingEnabled()) { - return ((TimeData)times.get(index)).getTime(); + return times.get(index).getTime(); } else { return 0; } @@ -264,7 +264,7 @@ */ public static String getMessageAtIndex(int index) { if (loggingEnabled()) { - return ((TimeData)times.get(index)).getMessage(); + return times.get(index).getMessage(); } else { return null; } @@ -278,7 +278,7 @@ try { synchronized(times) { for (int i = 0; i < times.size(); ++i) { - TimeData td = (TimeData)times.get(i); + TimeData td = times.get(i); if (td != null) { writer.write(i + " " + td.getMessage() + ": " + td.getTime() + "\n"); diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/misc/ProxyGenerator.java --- a/jdk/src/share/classes/sun/misc/ProxyGenerator.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/misc/ProxyGenerator.java Tue Mar 11 23:37:02 2008 -0700 @@ -324,8 +324,8 @@ if (saveGeneratedFiles) { java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { + new java.security.PrivilegedAction() { + public Void run() { try { FileOutputStream file = new FileOutputStream(dotToSlash(name) + ".class"); @@ -576,7 +576,7 @@ * compatibly with the throws clauses of both * overridden methods. */ - List legalExceptions = new ArrayList(); + List> legalExceptions = new ArrayList>(); collectCompatibleTypes( exceptionTypes, pm.exceptionTypes, legalExceptions); collectCompatibleTypes( @@ -618,11 +618,11 @@ * List of return types that are not yet known to be * assignable from ("covered" by) any of the others. */ - LinkedList uncoveredReturnTypes = new LinkedList(); + LinkedList> uncoveredReturnTypes = new LinkedList>(); nextNewReturnType: for (ProxyMethod pm : methods) { - Class newReturnType = pm.returnType; + Class newReturnType = pm.returnType; if (newReturnType.isPrimitive()) { throw new IllegalArgumentException( "methods with same signature " + @@ -637,9 +637,9 @@ * Compare the new return type to the existing uncovered * return types. */ - ListIterator liter = uncoveredReturnTypes.listIterator(); + ListIterator> liter = uncoveredReturnTypes.listIterator(); while (liter.hasNext()) { - Class uncoveredReturnType = liter.next(); + Class uncoveredReturnType = liter.next(); /* * If an existing uncovered return type is assignable @@ -944,10 +944,10 @@ tryEnd = pc = (short) minfo.code.size(); - List catchList = computeUniqueCatchList(exceptionTypes); + List> catchList = computeUniqueCatchList(exceptionTypes); if (catchList.size() > 0) { - for (Class ex : catchList) { + for (Class ex : catchList) { minfo.exceptionTable.add(new ExceptionTableEntry( tryBegin, tryEnd, pc, cp.getClass(dotToSlash(ex.getName())))); @@ -1521,8 +1521,9 @@ * declared exceptions from duplicate methods inherited from * different interfaces. */ - private static void collectCompatibleTypes(Class[] from, Class[] with, - List list) + private static void collectCompatibleTypes(Class[] from, + Class[] with, + List> list) { for (int i = 0; i < from.length; i++) { if (!list.contains(from[i])) { @@ -1557,8 +1558,8 @@ * given list of declared exceptions, indicating that no exceptions * need to be caught. */ - private static List computeUniqueCatchList(Class[] exceptions) { - List uniqueList = new ArrayList(); + private static List> computeUniqueCatchList(Class[] exceptions) { + List> uniqueList = new ArrayList>(); // unique exceptions to catch uniqueList.add(Error.class); // always catch/rethrow these @@ -1566,7 +1567,7 @@ nextException: for (int i = 0; i < exceptions.length; i++) { - Class ex = exceptions[i]; + Class ex = exceptions[i]; if (ex.isAssignableFrom(Throwable.class)) { /* * If Throwable is declared to be thrown by the proxy method, @@ -1586,7 +1587,7 @@ * exceptions that need to be caught: */ for (int j = 0; j < uniqueList.size();) { - Class ex2 = uniqueList.get(j); + Class ex2 = uniqueList.get(j); if (ex2.isAssignableFrom(ex)) { /* * if a superclass of this exception is already on diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/misc/URLClassPath.java --- a/jdk/src/share/classes/sun/misc/URLClassPath.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/misc/URLClassPath.java Tue Mar 11 23:37:02 2008 -0700 @@ -86,16 +86,16 @@ } /* The original search path of URLs. */ - private ArrayList path = new ArrayList(); + private ArrayList path = new ArrayList(); /* The stack of unopened URLs */ - Stack urls = new Stack(); + Stack urls = new Stack(); /* The resulting search path of Loaders */ - ArrayList loaders = new ArrayList(); + ArrayList loaders = new ArrayList(); /* Map of each URL opened to its corresponding Loader */ - HashMap lmap = new HashMap(); + HashMap lmap = new HashMap(); /* The jar protocol handler to use when creating new URLs */ private URLStreamHandler jarHandler; @@ -146,7 +146,7 @@ */ public URL[] getURLs() { synchronized (urls) { - return (URL[])path.toArray(new URL[path.size()]); + return path.toArray(new URL[path.size()]); } } @@ -200,9 +200,9 @@ * @param name the resource name * @return an Enumeration of all the urls having the specified name */ - public Enumeration findResources(final String name, + public Enumeration findResources(final String name, final boolean check) { - return new Enumeration() { + return new Enumeration() { private int index = 0; private URL url = null; @@ -225,7 +225,7 @@ return next(); } - public Object nextElement() { + public URL nextElement() { if (!next()) { throw new NoSuchElementException(); } @@ -247,9 +247,9 @@ * @param name the resource name * @return an Enumeration of all the resources having the specified name */ - public Enumeration getResources(final String name, + public Enumeration getResources(final String name, final boolean check) { - return new Enumeration() { + return new Enumeration() { private int index = 0; private Resource res = null; @@ -272,7 +272,7 @@ return next(); } - public Object nextElement() { + public Resource nextElement() { if (!next()) { throw new NoSuchElementException(); } @@ -283,7 +283,7 @@ }; } - public Enumeration getResources(final String name) { + public Enumeration getResources(final String name) { return getResources(name, true); } @@ -302,7 +302,7 @@ if (urls.empty()) { return null; } else { - url = (URL)urls.pop(); + url = urls.pop(); } } // Skip this URL if it already has a Loader. (Loader @@ -329,7 +329,7 @@ loaders.add(loader); lmap.put(url, loader); } - return (Loader)loaders.get(index); + return loaders.get(index); } /* @@ -337,9 +337,9 @@ */ private Loader getLoader(final URL url) throws IOException { try { - return (Loader)java.security.AccessController.doPrivileged - (new java.security.PrivilegedExceptionAction() { - public Object run() throws IOException { + return java.security.AccessController.doPrivileged( + new java.security.PrivilegedExceptionAction() { + public Loader run() throws IOException { String file = url.getFile(); if (file != null && file.endsWith("/")) { if ("file".equals(url.getProtocol())) { @@ -561,13 +561,14 @@ private JarIndex index; private MetaIndex metaIndex; private URLStreamHandler handler; - private HashMap lmap; + private HashMap lmap; /* * Creates a new JarLoader for the specified URL referring to * a JAR file. */ - JarLoader(URL url, URLStreamHandler jarHandler, HashMap loaderMap) + JarLoader(URL url, URLStreamHandler jarHandler, + HashMap loaderMap) throws IOException { super(new URL("jar", "", -1, url + "!/", jarHandler)); @@ -615,8 +616,8 @@ if (jar == null) { try { java.security.AccessController.doPrivileged( - new java.security.PrivilegedExceptionAction() { - public Object run() throws IOException { + new java.security.PrivilegedExceptionAction() { + public Void run() throws IOException { if (DEBUG) { System.err.println("Opening " + csu); Thread.dumpStack(); @@ -732,9 +733,9 @@ String entryName; ZipEntry entry; - Enumeration enum_ = jar.entries(); + Enumeration enum_ = jar.entries(); while (enum_.hasMoreElements()) { - entry = (ZipEntry)enum_.nextElement(); + entry = enum_.nextElement(); entryName = entry.getName(); if((pos = entryName.lastIndexOf("/")) != -1) entryName = entryName.substring(0, pos); @@ -778,7 +779,7 @@ if (index == null) return null; - HashSet visited = new HashSet(); + HashSet visited = new HashSet(); return getResource(name, check, visited); } @@ -790,7 +791,7 @@ * non-existent resource */ Resource getResource(final String name, boolean check, - Set visited) { + Set visited) { Resource res; Object[] jarFiles; @@ -819,10 +820,9 @@ /* no loader has been set up for this jar file * before */ - newLoader = (JarLoader) - AccessController.doPrivileged( - new PrivilegedExceptionAction() { - public Object run() throws IOException { + newLoader = AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public JarLoader run() throws IOException { return new JarLoader(url, handler, lmap); } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/net/NetProperties.java --- a/jdk/src/share/classes/sun/net/NetProperties.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/net/NetProperties.java Tue Mar 11 23:37:02 2008 -0700 @@ -42,8 +42,8 @@ static private Properties props = new Properties(); static { AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { + new PrivilegedAction() { + public Void run() { loadDefaultProperties(); return null; }}); diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/net/NetworkClient.java --- a/jdk/src/share/classes/sun/net/NetworkClient.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/net/NetworkClient.java Tue Mar 11 23:37:02 2008 -0700 @@ -64,8 +64,8 @@ final String encs[] = { null }; AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { + new PrivilegedAction() { + public Void run() { vals[0] = Integer.getInteger("sun.net.client.defaultReadTimeout", 0).intValue(); vals[1] = Integer.getInteger("sun.net.client.defaultConnectTimeout", 0).intValue(); encs[0] = System.getProperty("file.encoding", "ISO8859_1"); @@ -152,9 +152,9 @@ Socket s; if (proxy != null) { if (proxy.type() == Proxy.Type.SOCKS) { - s = (Socket) AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { + s = AccessController.doPrivileged( + new PrivilegedAction() { + public Socket run() { return new Socket(proxy); }}); } else diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/net/ftp/FtpClient.java --- a/jdk/src/share/classes/sun/net/ftp/FtpClient.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/net/ftp/FtpClient.java Tue Mar 11 23:37:02 2008 -0700 @@ -117,8 +117,8 @@ public static int getFtpProxyPort() { final int result[] = {80}; java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { + new java.security.PrivilegedAction() { + public Void run() { String tmp = System.getProperty("ftp.proxyPort"); if (tmp == null) { @@ -343,9 +343,9 @@ Socket s; if (proxy != null) { if (proxy.type() == Proxy.Type.SOCKS) { - s = (Socket) AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { + s = AccessController.doPrivileged( + new PrivilegedAction() { + public Socket run() { return new Socket(proxy); }}); } else diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/net/spi/DefaultProxySelector.java --- a/jdk/src/share/classes/sun/net/spi/DefaultProxySelector.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/net/spi/DefaultProxySelector.java Tue Mar 11 23:37:02 2008 -0700 @@ -82,9 +82,9 @@ static { final String key = "java.net.useSystemProxies"; - Boolean b = (Boolean) AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { + Boolean b = AccessController.doPrivileged( + new PrivilegedAction() { + public Boolean run() { return NetProperties.getBoolean(key); }}); if (b != null && b.booleanValue()) { @@ -197,9 +197,9 @@ * System properties it does help having only 1 call to doPrivileged. * Be mindful what you do in here though! */ - Proxy p = (Proxy) AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { + Proxy p = AccessController.doPrivileged( + new PrivilegedAction() { + public Proxy run() { int i, j; String phost = null; int pport = 0; diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/net/www/MessageHeader.java --- a/jdk/src/share/classes/sun/net/www/MessageHeader.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/net/www/MessageHeader.java Tue Mar 11 23:37:02 2008 -0700 @@ -138,7 +138,7 @@ return null; } - class HeaderIterator implements Iterator { + class HeaderIterator implements Iterator { int index = 0; int next = -1; String key; @@ -165,7 +165,7 @@ return false; } } - public Object next() { + public String next() { synchronized (lock) { if (haveNext) { haveNext = false; @@ -187,17 +187,17 @@ * return an Iterator that returns all values of a particular * key in sequence */ - public Iterator multiValueIterator (String k) { + public Iterator multiValueIterator (String k) { return new HeaderIterator (k, this); } - public synchronized Map getHeaders() { + public synchronized Map> getHeaders() { return getHeaders(null); } - public synchronized Map getHeaders(String[] excludeList) { + public synchronized Map> getHeaders(String[] excludeList) { boolean skipIt = false; - Map m = new HashMap(); + Map> m = new HashMap>(); for (int i = nkeys; --i >= 0;) { if (excludeList != null) { // check if the key is in the excludeList. @@ -211,9 +211,9 @@ } } if (!skipIt) { - List l = (List)m.get(keys[i]); + List l = m.get(keys[i]); if (l == null) { - l = new ArrayList(); + l = new ArrayList(); m.put(keys[i], l); } l.add(values[i]); @@ -223,11 +223,8 @@ } } - Set keySet = m.keySet(); - for (Iterator i = keySet.iterator(); i.hasNext();) { - Object key = i.next(); - List l = (List)m.get(key); - m.put(key, Collections.unmodifiableList(l)); + for (String key : m.keySet()) { + m.put(key, Collections.unmodifiableList(m.get(key))); } return Collections.unmodifiableMap(m); diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/net/www/MimeTable.java --- a/jdk/src/share/classes/sun/net/www/MimeTable.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/net/www/MimeTable.java Tue Mar 11 23:37:02 2008 -0700 @@ -37,18 +37,20 @@ public class MimeTable implements FileNameMap { /** Keyed by content type, returns MimeEntries */ - private Hashtable entries = new Hashtable(); + private Hashtable entries + = new Hashtable(); /** Keyed by file extension (with the .), returns MimeEntries */ - private Hashtable extensionMap = new Hashtable(); + private Hashtable extensionMap + = new Hashtable(); // Will be reset if in the platform-specific data file private static String tempFileTemplate; static { java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { + new java.security.PrivilegedAction() { + public Void run() { tempFileTemplate = System.getProperty("content.types.temp.file.template", "/tmp/%s"); @@ -60,7 +62,8 @@ "/usr/etc/mailcap", "/usr/local/etc/mailcap", System.getProperty("hotjava.home", - "/usr/local/hotjava") + "/lib/mailcap", + "/usr/local/hotjava") + + "/lib/mailcap", }; return null; } @@ -83,8 +86,8 @@ public static MimeTable getDefaultTable() { if (defaultInstance == null) { java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { + new java.security.PrivilegedAction() { + public Void run() { defaultInstance = new MimeTable(); URLConnection.setFileNameMap(defaultInstance); return null; @@ -130,7 +133,7 @@ } public synchronized MimeEntry remove(String type) { - MimeEntry entry = (MimeEntry)entries.get(type); + MimeEntry entry = entries.get(type); return remove(entry); } @@ -142,16 +145,16 @@ } } - return (MimeEntry)entries.remove(entry.getType()); + return entries.remove(entry.getType()); } public synchronized MimeEntry find(String type) { - MimeEntry entry = (MimeEntry)entries.get(type); + MimeEntry entry = entries.get(type); if (entry == null) { // try a wildcard lookup - Enumeration e = entries.elements(); + Enumeration e = entries.elements(); while (e.hasMoreElements()) { - MimeEntry wild = (MimeEntry)e.nextElement(); + MimeEntry wild = e.nextElement(); if (wild.matches(type)) { return wild; } @@ -191,13 +194,13 @@ * with it. */ public synchronized MimeEntry findByExt(String fileExtension) { - return (MimeEntry)extensionMap.get(fileExtension); + return extensionMap.get(fileExtension); } public synchronized MimeEntry findByDescription(String description) { - Enumeration e = elements(); + Enumeration e = elements(); while (e.hasMoreElements()) { - MimeEntry entry = (MimeEntry)e.nextElement(); + MimeEntry entry = e.nextElement(); if (description.equals(entry.getDescription())) { return entry; } @@ -211,7 +214,7 @@ return tempFileTemplate; } - public synchronized Enumeration elements() { + public synchronized Enumeration elements() { return entries.elements(); } @@ -269,7 +272,7 @@ } // now, parse the mime-type spec's - Enumeration types = entries.propertyNames(); + Enumeration types = entries.propertyNames(); while (types.hasMoreElements()) { String type = (String)types.nextElement(); String attrs = entries.getProperty(type); @@ -392,9 +395,9 @@ public Properties getAsProperties() { Properties properties = new Properties(); - Enumeration e = elements(); + Enumeration e = elements(); while (e.hasMoreElements()) { - MimeEntry entry = (MimeEntry)e.nextElement(); + MimeEntry entry = e.nextElement(); properties.put(entry.getType(), entry.toProperty()); } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/net/www/http/HttpClient.java --- a/jdk/src/share/classes/sun/net/www/http/HttpClient.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/net/www/http/HttpClient.java Tue Mar 11 23:37:02 2008 -0700 @@ -230,9 +230,9 @@ setConnectTimeout(to); // get the cookieHandler if there is any - cookieHandler = (CookieHandler)java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { + cookieHandler = java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public CookieHandler run() { return CookieHandler.getDefault(); } }); @@ -297,7 +297,7 @@ HttpClient ret = null; /* see if one's already around */ if (useCache) { - ret = (HttpClient) kac.get(url, null); + ret = kac.get(url, null); if (ret != null) { if ((ret.proxy != null && ret.proxy.equals(p)) || (ret.proxy == null && p == null)) { @@ -389,7 +389,7 @@ * cache). */ public void closeIdleConnection() { - HttpClient http = (HttpClient) kac.get(url, null); + HttpClient http = kac.get(url, null); if (http != null) { http.closeServer(); } @@ -447,8 +447,8 @@ { try { java.security.AccessController.doPrivileged( - new java.security.PrivilegedExceptionAction() { - public Object run() throws IOException { + new java.security.PrivilegedExceptionAction() { + public Void run() throws IOException { openServer(server.getHostString(), server.getPort()); return null; } @@ -477,9 +477,8 @@ { try { java.security.AccessController.doPrivileged( - new java.security.PrivilegedExceptionAction() { - public Object run() throws IOException - { + new java.security.PrivilegedExceptionAction() { + public Void run() throws IOException { superOpenServer(proxyHost, proxyPort); return null; } @@ -686,7 +685,7 @@ // So we do put the cast in as a workaround until // it is resolved. if (uri != null) - cookieHandler.put(uri, (Map>)responses.getHeaders()); + cookieHandler.put(uri, responses.getHeaders()); } /* decide if we're keeping alive: diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java --- a/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java Tue Mar 11 23:37:02 2008 -0700 @@ -38,7 +38,9 @@ * @author Stephen R. Pietrowicz (NCSA) * @author Dave Brown */ -public class KeepAliveCache extends ConcurrentHashMap implements Runnable { +public class KeepAliveCache + extends ConcurrentHashMap + implements Runnable { private static final long serialVersionUID = -2937172892064557949L; /* maximum # keep-alive connections to maintain at once @@ -88,12 +90,12 @@ * back from the server. If I'm connected through a Netscape proxy * to a server that sent me a keep-alive * time of 15 sec, the proxy unilaterally terminates my connection - * The robustness to to get around this is in HttpClient.parseHTTP() + * The robustness to get around this is in HttpClient.parseHTTP() */ final KeepAliveCache cache = this; java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { + new java.security.PrivilegedAction() { + public Void run() { // We want to create the Keep-Alive-Timer in the // system threadgroup ThreadGroup grp = Thread.currentThread().getThreadGroup(); @@ -112,7 +114,7 @@ } KeepAliveKey key = new KeepAliveKey(url, obj); - ClientVector v = (ClientVector)super.get(key); + ClientVector v = super.get(key); if (v == null) { int keepAliveTimeout = http.getKeepAliveTimeout(); @@ -125,10 +127,10 @@ } } - /* remove an obsolete HttpClient from it's VectorCache */ + /* remove an obsolete HttpClient from its VectorCache */ public synchronized void remove (HttpClient h, Object obj) { KeepAliveKey key = new KeepAliveKey(h.url, obj); - ClientVector v = (ClientVector)super.get(key); + ClientVector v = super.get(key); if (v != null) { v.remove(h); if (v.empty()) { @@ -137,7 +139,7 @@ } } - /* called by a clientVector thread when all it's connections have timed out + /* called by a clientVector thread when all its connections have timed out * and that vector of connections should be removed. */ synchronized void removeVector(KeepAliveKey k) { @@ -147,10 +149,10 @@ /** * Check to see if this URL has a cached HttpClient */ - public synchronized Object get(URL url, Object obj) { + public synchronized HttpClient get(URL url, Object obj) { KeepAliveKey key = new KeepAliveKey(url, obj); - ClientVector v = (ClientVector)super.get(key); + ClientVector v = super.get(key); if (v == null) { // nothing in cache yet return null; } @@ -180,17 +182,16 @@ long currentTime = System.currentTimeMillis(); - Iterator itr = keySet().iterator(); - ArrayList keysToRemove = new ArrayList(); + ArrayList keysToRemove + = new ArrayList(); - while (itr.hasNext()) { - KeepAliveKey key = (KeepAliveKey)itr.next(); - ClientVector v = (ClientVector)get(key); + for (KeepAliveKey key : keySet()) { + ClientVector v = get(key); synchronized (v) { int i; for (i = 0; i < v.size(); i++) { - KeepAliveEntry e = (KeepAliveEntry)v.elementAt(i); + KeepAliveEntry e = v.elementAt(i); if ((currentTime - e.idleStartTime) > v.nap) { HttpClient h = e.hc; h.closeServer(); @@ -205,9 +206,9 @@ } } } - itr = keysToRemove.iterator(); - while (itr.hasNext()) { - removeVector((KeepAliveKey)itr.next()); + + for (KeepAliveKey key : keysToRemove) { + removeVector(key); } } } while (size() > 0); @@ -234,7 +235,7 @@ */ -class ClientVector extends java.util.Stack { +class ClientVector extends java.util.Stack { private static final long serialVersionUID = -8680532108106489459L; // sleep time in milliseconds, before cache clear @@ -254,7 +255,7 @@ HttpClient hc = null; long currentTime = System.currentTimeMillis(); do { - KeepAliveEntry e = (KeepAliveEntry)pop(); + KeepAliveEntry e = pop(); if ((currentTime - e.idleStartTime) > nap) { e.hc.closeServer(); } else { diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/net/www/http/KeepAliveStream.java --- a/jdk/src/share/classes/sun/net/www/http/KeepAliveStream.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/net/www/http/KeepAliveStream.java Tue Mar 11 23:37:02 2008 -0700 @@ -174,8 +174,8 @@ if (startCleanupThread) { java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { + new java.security.PrivilegedAction() { + public Void run() { // We want to create the Keep-Alive-SocketCleaner in the // system threadgroup ThreadGroup grp = Thread.currentThread().getThreadGroup(); diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/net/www/http/KeepAliveStreamCleaner.java --- a/jdk/src/share/classes/sun/net/www/http/KeepAliveStreamCleaner.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/net/www/http/KeepAliveStreamCleaner.java Tue Mar 11 23:37:02 2008 -0700 @@ -59,19 +59,19 @@ static { final String maxDataKey = "http.KeepAlive.remainingData"; - int maxData = ((Integer) AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { - return new Integer(NetProperties.getInteger(maxDataKey, MAX_DATA_REMAINING)); - }})).intValue() * 1024; + int maxData = AccessController.doPrivileged( + new PrivilegedAction() { + public Integer run() { + return NetProperties.getInteger(maxDataKey, MAX_DATA_REMAINING); + }}).intValue() * 1024; MAX_DATA_REMAINING = maxData; final String maxCapacityKey = "http.KeepAlive.queuedConnections"; - int maxCapacity = ((Integer) AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { - return new Integer(NetProperties.getInteger(maxCapacityKey, MAX_CAPACITY)); - }})).intValue(); + int maxCapacity = AccessController.doPrivileged( + new PrivilegedAction() { + public Integer run() { + return NetProperties.getInteger(maxCapacityKey, MAX_CAPACITY); + }}).intValue(); MAX_CAPACITY = maxCapacity; } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java --- a/jdk/src/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java Tue Mar 11 23:37:02 2008 -0700 @@ -215,12 +215,11 @@ Proxy p = null; if (instProxy == null) { // no per connection proxy specified /** - * Do we have to use a proxie? + * Do we have to use a proxy? */ - ProxySelector sel = (ProxySelector) - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { + ProxySelector sel = java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public ProxySelector run() { return ProxySelector.getDefault(); } }); diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java --- a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Tue Mar 11 23:37:02 2008 -0700 @@ -139,8 +139,8 @@ static { maxRedirects = java.security.AccessController.doPrivileged( - new sun.security.action.GetIntegerAction("http.maxRedirects", - defaultmaxRedirects)).intValue(); + new sun.security.action.GetIntegerAction( + "http.maxRedirects", defaultmaxRedirects)).intValue(); version = java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("java.version")); String agent = java.security.AccessController.doPrivileged( @@ -286,10 +286,9 @@ final String scheme, final URL url, final RequestorType authType) { - return (PasswordAuthentication) - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { + return java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public PasswordAuthentication run() { return Authenticator.requestPasswordAuthentication( host, addr, port, protocol, prompt, scheme, url, authType); @@ -554,15 +553,15 @@ responses = new MessageHeader(); this.handler = handler; instProxy = p; - cookieHandler = (CookieHandler)java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { + cookieHandler = java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public CookieHandler run() { return CookieHandler.getDefault(); } }); - cacheHandler = (ResponseCache)java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { + cacheHandler = java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public ResponseCache run() { return ResponseCache.getDefault(); } }); @@ -645,8 +644,8 @@ final boolean result[] = {false}; java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { + new java.security.PrivilegedAction() { + public Void run() { try { InetAddress a1 = InetAddress.getByName(h1); InetAddress a2 = InetAddress.getByName(h2); @@ -724,10 +723,10 @@ /** * Do we have to use a proxy? */ - ProxySelector sel = (ProxySelector) + ProxySelector sel = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { + new java.security.PrivilegedAction() { + public ProxySelector run() { return ProxySelector.getDefault(); } }); @@ -904,9 +903,12 @@ URI uri = ParseUtil.toURI(url); if (uri != null) { - Map> cookies = cookieHandler.get(uri, requests.getHeaders(EXCLUDE_HEADERS)); + Map> cookies + = cookieHandler.get( + uri, requests.getHeaders(EXCLUDE_HEADERS)); if (!cookies.isEmpty()) { - for (Map.Entry> entry : cookies.entrySet()) { + for (Map.Entry> entry : + cookies.entrySet()) { String key = entry.getKey(); // ignore all entries that don't have "Cookie" // or "Cookie2" as keys @@ -1356,23 +1358,20 @@ * original exception and with the same message. Right now, * there is no convenient APIs for doing so. */ - private IOException getChainedException(IOException rememberedException) { + private IOException getChainedException(final IOException rememberedException) { try { - final IOException originalException = rememberedException; - final Class[] cls = new Class[1]; - cls[0] = String.class; - final String[] args = new String[1]; - args[0] = originalException.getMessage(); - IOException chainedException = (IOException) - java.security.AccessController.doPrivileged - (new java.security.PrivilegedExceptionAction() { - public Object run() - throws Exception { - Constructor ctr = originalException.getClass().getConstructor(cls); - return (IOException)ctr.newInstance((Object[])args); + final Object[] args = { rememberedException.getMessage() }; + IOException chainedException = + java.security.AccessController.doPrivileged( + new java.security.PrivilegedExceptionAction() { + public IOException run() throws Exception { + return (IOException) + rememberedException.getClass() + .getConstructor(new Class[] { String.class }) + .newInstance(args); } }); - chainedException.initCause(originalException); + chainedException.initCause(rememberedException); return chainedException; } catch (Exception ignored) { return rememberedException; @@ -1623,10 +1622,9 @@ InetAddress addr = null; try { final String finalHost = host; - addr = (InetAddress) - java.security.AccessController.doPrivileged - (new java.security.PrivilegedExceptionAction() { - public Object run() + addr = java.security.AccessController.doPrivileged( + new java.security.PrivilegedExceptionAction() { + public InetAddress run() throws java.net.UnknownHostException { return InetAddress.getByName(finalHost); } @@ -2171,7 +2169,7 @@ * @since 1.4 */ @Override - public Map getHeaderFields() { + public Map> getHeaderFields() { try { getInputStream(); } catch (IOException e) {} @@ -2289,7 +2287,7 @@ * @since 1.4 */ @Override - public Map getRequestProperties() { + public Map> getRequestProperties() { if (connected) throw new IllegalStateException("Already connected"); @@ -2375,20 +2373,15 @@ return method; } - private MessageHeader mapToMessageHeader(Map map) { + private MessageHeader mapToMessageHeader(Map> map) { MessageHeader headers = new MessageHeader(); if (map == null || map.isEmpty()) { return headers; } - Set entries = map.entrySet(); - Iterator itr1 = entries.iterator(); - while (itr1.hasNext()) { - Map.Entry entry = (Map.Entry)itr1.next(); - String key = (String)entry.getKey(); - List values = (List)entry.getValue(); - Iterator itr2 = values.iterator(); - while (itr2.hasNext()) { - String value = (String)itr2.next(); + for (Map.Entry> entry : map.entrySet()) { + String key = entry.getKey(); + List values = entry.getValue(); + for (String value : values) { if (key == null) { headers.prepend(key, value); } else { diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/net/www/protocol/jar/URLJarFile.java --- a/jdk/src/share/classes/sun/net/www/protocol/jar/URLJarFile.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/net/www/protocol/jar/URLJarFile.java Tue Mar 11 23:37:02 2008 -0700 @@ -55,7 +55,7 @@ private Manifest superMan; private Attributes superAttr; - private Map superEntries; + private Map superEntries; static JarFile getJarFile(URL url) throws IOException { return getJarFile(url, null); @@ -146,12 +146,10 @@ // now deep copy the manifest entries if (superEntries != null) { - Map entries = man.getEntries(); - Iterator it = superEntries.keySet().iterator(); - while (it.hasNext()) { - Object key = it.next(); - Attributes at = (Attributes)superEntries.get(key); - entries.put(key, at.clone()); + Map entries = man.getEntries(); + for (String key : superEntries.keySet()) { + Attributes at = superEntries.get(key); + entries.put(key, (Attributes) at.clone()); } } @@ -213,9 +211,9 @@ final InputStream in = url.openConnection().getInputStream(); try { - result = (JarFile) - AccessController.doPrivileged(new PrivilegedExceptionAction() { - public Object run() throws IOException { + result = AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public JarFile run() throws IOException { OutputStream out = null; File tmpFile = null; try { @@ -273,9 +271,9 @@ public Attributes getAttributes() throws IOException { if (URLJarFile.this.isSuperMan()) { - Map e = URLJarFile.this.superEntries; + Map e = URLJarFile.this.superEntries; if (e != null) { - Attributes a = (Attributes)e.get(getName()); + Attributes a = e.get(getName()); if (a != null) return (Attributes)a.clone(); } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java --- a/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java Tue Mar 11 23:37:02 2008 -0700 @@ -52,39 +52,37 @@ { // Used to make native read and write calls - private static NativeDispatcher nd; + private static final NativeDispatcher nd; // Memory allocation size for mapping buffers - private static long allocationGranularity; + private static final long allocationGranularity; // Cached field for MappedByteBuffer.isAMappedBuffer - private static Field isAMappedBufferField; + private static final Field isAMappedBufferField; // File descriptor - private FileDescriptor fd; + private final FileDescriptor fd; // File access mode (immutable) - private boolean writable; - private boolean readable; - private boolean appending; + private final boolean writable; + private final boolean readable; // Required to prevent finalization of creating stream (immutable) - private Object parent; + private final Object parent; // Thread-safe set of IDs of native threads, for signalling - private NativeThreadSet threads = new NativeThreadSet(2); + private final NativeThreadSet threads = new NativeThreadSet(2); // Lock for operations involving position and size - private Object positionLock = new Object(); + private final Object positionLock = new Object(); private FileChannelImpl(FileDescriptor fd, boolean readable, - boolean writable, Object parent, boolean append) + boolean writable, Object parent) { this.fd = fd; this.readable = readable; this.writable = writable; this.parent = parent; - this.appending = append; } // Invoked by getChannel() methods @@ -94,14 +92,7 @@ boolean readable, boolean writable, Object parent) { - return new FileChannelImpl(fd, readable, writable, parent, false); - } - - public static FileChannel open(FileDescriptor fd, - boolean readable, boolean writable, - Object parent, boolean append) - { - return new FileChannelImpl(fd, readable, writable, parent, append); + return new FileChannelImpl(fd, readable, writable, parent); } private void ensureOpen() throws IOException { @@ -134,15 +125,7 @@ // superclass AbstractInterruptibleChannel, but the isOpen logic in // that method will prevent this method from being reinvoked. // - if (parent instanceof FileInputStream) - ((FileInputStream)parent).close(); - else if (parent instanceof FileOutputStream) - ((FileOutputStream)parent).close(); - else if (parent instanceof RandomAccessFile) - ((RandomAccessFile)parent).close(); - else - assert false; - + ((java.io.Closeable)parent).close(); } else { nd.close(fd); } @@ -218,8 +201,6 @@ if (!isOpen()) return 0; ti = threads.add(); - if (appending) - position(size()); do { n = IOUtil.write(fd, src, -1, nd, positionLock); } while ((n == IOStatus.INTERRUPTED) && isOpen()); @@ -244,8 +225,6 @@ if (!isOpen()) return 0; ti = threads.add(); - if (appending) - position(size()); do { n = IOUtil.write(fd, srcs, nd); } while ((n == IOStatus.INTERRUPTED) && isOpen()); @@ -1051,7 +1030,7 @@ private FileKey fileKey; FileLockReference(FileLock referent, - ReferenceQueue queue, + ReferenceQueue queue, FileKey key) { super(referent, queue); this.fileKey = key; @@ -1073,7 +1052,7 @@ new ConcurrentHashMap>(); // reference queue for cleared refs - private static ReferenceQueue queue = new ReferenceQueue(); + private static ReferenceQueue queue = new ReferenceQueue(); // the enclosing file channel private FileChannelImpl fci; diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/nio/ch/Reflect.java --- a/jdk/src/share/classes/sun/nio/ch/Reflect.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/nio/ch/Reflect.java Tue Mar 11 23:37:02 2008 -0700 @@ -43,8 +43,8 @@ } private static void setAccessible(final AccessibleObject ao) { - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { ao.setAccessible(true); return null; }}); @@ -54,7 +54,7 @@ Class[] paramTypes) { try { - Class cl = Class.forName(className); + Class cl = Class.forName(className); Constructor c = cl.getDeclaredConstructor(paramTypes); setAccessible(c); return c; @@ -82,7 +82,7 @@ Class[] paramTypes) { try { - Class cl = Class.forName(className); + Class cl = Class.forName(className); Method m = cl.getDeclaredMethod(methodName, paramTypes); setAccessible(m); return m; diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/nio/ch/SocketAdaptor.java --- a/jdk/src/share/classes/sun/nio/ch/SocketAdaptor.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/nio/ch/SocketAdaptor.java Tue Mar 11 23:37:02 2008 -0700 @@ -242,9 +242,9 @@ throw new SocketException("Socket input is shutdown"); if (socketInputStream == null) { try { - socketInputStream = (InputStream)AccessController.doPrivileged( - new PrivilegedExceptionAction() { - public Object run() throws IOException { + socketInputStream = AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public InputStream run() throws IOException { return new SocketInputStream(); } }); @@ -264,9 +264,9 @@ throw new SocketException("Socket output is shutdown"); OutputStream os = null; try { - os = (OutputStream) - AccessController.doPrivileged(new PrivilegedExceptionAction() { - public Object run() throws IOException { + os = AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public OutputStream run() throws IOException { return Channels.newOutputStream(sc); } }); diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/nio/ch/Util.java --- a/jdk/src/share/classes/sun/nio/ch/Util.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/nio/ch/Util.java Tue Mar 11 23:37:02 2008 -0700 @@ -49,20 +49,21 @@ private static final int TEMP_BUF_POOL_SIZE = 3; // Per-thread soft cache of the last temporary direct buffer - private static ThreadLocal[] bufferPool; + private static ThreadLocal>[] bufferPool; static { - bufferPool = new ThreadLocal[TEMP_BUF_POOL_SIZE]; + bufferPool = (ThreadLocal>[]) + new ThreadLocal[TEMP_BUF_POOL_SIZE]; for (int i=0; i>(); } static ByteBuffer getTemporaryDirectBuffer(int size) { ByteBuffer buf = null; // Grab a buffer if available for (int i=0; i ref = bufferPool[i].get(); + if ((ref != null) && ((buf = ref.get()) != null) && (buf.capacity() >= size)) { buf.rewind(); buf.limit(size); @@ -80,18 +81,18 @@ return; // Put it in an empty slot if such exists for (int i=0; i ref = bufferPool[i].get(); if ((ref == null) || (ref.get() == null)) { - bufferPool[i].set(new SoftReference(buf)); + bufferPool[i].set(new SoftReference(buf)); return; } } // Otherwise replace a smaller one in the cache if such exists for (int i=0; i ref = bufferPool[i].get(); + ByteBuffer inCacheBuf = ref.get(); if ((inCacheBuf == null) || (buf.capacity() > inCacheBuf.capacity())) { - bufferPool[i].set(new SoftReference(buf)); + bufferPool[i].set(new SoftReference(buf)); return; } } @@ -120,10 +121,12 @@ } // Per-thread cached selector - private static ThreadLocal localSelector = new ThreadLocal(); + private static ThreadLocal> localSelector + = new ThreadLocal>(); // Hold a reference to the selWrapper object to prevent it from // being cleaned when the temporary selector wrapped is on lease. - private static ThreadLocal localSelectorWrapper = new ThreadLocal(); + private static ThreadLocal localSelectorWrapper + = new ThreadLocal(); // When finished, invoker must ensure that selector is empty // by cancelling any related keys and explicitly releasing @@ -131,15 +134,16 @@ static Selector getTemporarySelector(SelectableChannel sc) throws IOException { - SoftReference ref = (SoftReference)localSelector.get(); + SoftReference ref = localSelector.get(); SelectorWrapper selWrapper = null; Selector sel = null; if (ref == null - || ((selWrapper = (SelectorWrapper) ref.get()) == null) + || ((selWrapper = ref.get()) == null) || ((sel = selWrapper.get()) == null) || (sel.provider() != sc.provider())) { sel = sc.provider().openSelector(); - localSelector.set(new SoftReference(new SelectorWrapper(sel))); + localSelector.set(new SoftReference( + new SelectorWrapper(sel))); } else { localSelectorWrapper.set(selWrapper); } @@ -235,10 +239,10 @@ private static volatile Constructor directByteBufferConstructor = null; private static void initDBBConstructor() { - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { try { - Class cl = Class.forName("java.nio.DirectByteBuffer"); + Class cl = Class.forName("java.nio.DirectByteBuffer"); Constructor ctor = cl.getDeclaredConstructor( new Class[] { int.class, long.class, @@ -282,10 +286,10 @@ private static volatile Constructor directByteBufferRConstructor = null; private static void initDBBRConstructor() { - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { try { - Class cl = Class.forName("java.nio.DirectByteBufferR"); + Class cl = Class.forName("java.nio.DirectByteBufferR"); Constructor ctor = cl.getDeclaredConstructor( new Class[] { int.class, long.class, diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/reflect/ClassDefiner.java --- a/jdk/src/share/classes/sun/reflect/ClassDefiner.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/reflect/ClassDefiner.java Tue Mar 11 23:37:02 2008 -0700 @@ -54,9 +54,9 @@ static Class defineClass(String name, byte[] bytes, int off, int len, final ClassLoader parentClassLoader) { - ClassLoader newLoader = (ClassLoader) - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + ClassLoader newLoader = AccessController.doPrivileged( + new PrivilegedAction() { + public ClassLoader run() { return new DelegatingClassLoader(parentClassLoader); } }); diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/reflect/MethodAccessorGenerator.java --- a/jdk/src/share/classes/sun/reflect/MethodAccessorGenerator.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/reflect/MethodAccessorGenerator.java Tue Mar 11 23:37:02 2008 -0700 @@ -392,11 +392,12 @@ // same namespace as the target class. Since the generated code // is privileged anyway, the protection domain probably doesn't // matter. - return (MagicAccessorImpl) - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + return AccessController.doPrivileged( + new PrivilegedAction() { + public MagicAccessorImpl run() { try { - return ClassDefiner.defineClass + return (MagicAccessorImpl) + ClassDefiner.defineClass (generatedName, bytes, 0, diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/reflect/ReflectionFactory.java --- a/jdk/src/share/classes/sun/reflect/ReflectionFactory.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/reflect/ReflectionFactory.java Tue Mar 11 23:37:02 2008 -0700 @@ -84,8 +84,8 @@ * AccessController.doPrivileged. */ public static final class GetReflectionFactoryAction - implements PrivilegedAction { - public Object run() { + implements PrivilegedAction { + public ReflectionFactory run() { return getReflectionFactory(); } } @@ -164,7 +164,7 @@ public ConstructorAccessor newConstructorAccessor(Constructor c) { checkInitted(); - Class declaringClass = c.getDeclaringClass(); + Class declaringClass = c.getDeclaringClass(); if (Modifier.isAbstract(declaringClass.getModifiers())) { return new InstantiationExceptionConstructorAccessorImpl(null); } @@ -204,9 +204,9 @@ /** Creates a new java.lang.reflect.Field. Access checks as per java.lang.reflect.AccessibleObject are not overridden. */ - public Field newField(Class declaringClass, + public Field newField(Class declaringClass, String name, - Class type, + Class type, int modifiers, int slot, String signature, @@ -223,11 +223,11 @@ /** Creates a new java.lang.reflect.Method. Access checks as per java.lang.reflect.AccessibleObject are not overridden. */ - public Method newMethod(Class declaringClass, + public Method newMethod(Class declaringClass, String name, - Class[] parameterTypes, - Class returnType, - Class[] checkedExceptions, + Class[] parameterTypes, + Class returnType, + Class[] checkedExceptions, int modifiers, int slot, String signature, @@ -250,9 +250,9 @@ /** Creates a new java.lang.reflect.Constructor. Access checks as per java.lang.reflect.AccessibleObject are not overridden. */ - public Constructor newConstructor(Class declaringClass, - Class[] parameterTypes, - Class[] checkedExceptions, + public Constructor newConstructor(Class declaringClass, + Class[] parameterTypes, + Class[] checkedExceptions, int modifiers, int slot, String signature, @@ -310,7 +310,7 @@ /** Makes a copy of the passed constructor. The returned constructor is a "child" of the passed one; see the comments in Constructor.java for details. */ - public Constructor copyConstructor(Constructor arg) { + public Constructor copyConstructor(Constructor arg) { return langReflectAccess().copyConstructor(arg); } @@ -321,7 +321,7 @@ // public Constructor newConstructorForSerialization - (Class classToInstantiate, Constructor constructorToCall) + (Class classToInstantiate, Constructor constructorToCall) { // Fast path if (constructorToCall.getDeclaringClass() == classToInstantiate) { @@ -366,8 +366,9 @@ run, before the system properties are set up. */ private static void checkInitted() { if (initted) return; - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + AccessController.doPrivileged( + new PrivilegedAction() { + public Void run() { // Tests to ensure the system properties table is fully // initialized. This is needed because reflection code is // called very early in the initialization process (before diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java --- a/jdk/src/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java Tue Mar 11 23:37:02 2008 -0700 @@ -273,8 +273,8 @@ private Method[] getMemberMethods() { if (memberMethods == null) { final Method[] mm = type.getDeclaredMethods(); - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { AccessibleObject.setAccessible(mm, true); return null; } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/reflect/misc/MethodUtil.java --- a/jdk/src/share/classes/sun/reflect/misc/MethodUtil.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/reflect/misc/MethodUtil.java Tue Mar 11 23:37:02 2008 -0700 @@ -67,7 +67,7 @@ super(); } - public static Method getMethod(Class cls, String name, Class[] args) + public static Method getMethod(Class cls, String name, Class[] args) throws NoSuchMethodException { ReflectUtil.checkPackageAccess(cls); return cls.getMethod(name, args); @@ -89,7 +89,7 @@ if (System.getSecurityManager() == null) { return cls.getMethods(); } - Map sigs = new HashMap(); + Map sigs = new HashMap(); while (cls != null) { boolean done = getInternalPublicMethods(cls, sigs); if (done) { @@ -98,14 +98,14 @@ getInterfaceMethods(cls, sigs); cls = cls.getSuperclass(); } - Collection c = sigs.values(); - return (Method[]) c.toArray(new Method[c.size()]); + return sigs.values().toArray(new Method[sigs.size()]); } /* * Process the immediate interfaces of this class or interface. */ - private static void getInterfaceMethods(Class cls, Map sigs) { + private static void getInterfaceMethods(Class cls, + Map sigs) { Class[] intfs = cls.getInterfaces(); for (int i=0; i < intfs.length; i++) { Class intf = intfs[i]; @@ -120,7 +120,8 @@ * * Process the methods in this class or interface */ - private static boolean getInternalPublicMethods(Class cls, Map sigs) { + private static boolean getInternalPublicMethods(Class cls, + Map sigs) { Method[] methods = null; try { /* @@ -178,7 +179,7 @@ return done; } - private static void addMethod(Map sigs, Method method) { + private static void addMethod(Map sigs, Method method) { Signature signature = new Signature(method); if (!sigs.containsKey(signature)) { sigs.put(signature, method); @@ -186,7 +187,7 @@ /* * Superclasses beat interfaces. */ - Method old = (Method)sigs.get(signature); + Method old = sigs.get(signature); if (old.getDeclaringClass().isInterface()) { sigs.put(signature, method); } @@ -280,17 +281,15 @@ } private static Method getTrampoline() { - Method tramp = null; - try { - tramp = (Method) AccessController.doPrivileged(new PrivilegedExceptionAction() { - public Object run() throws Exception { - Class[] types; - Class t = getTrampolineClass(); - Method b; - - types = new Class[] {Method.class, Object.class, Object[].class}; - b = t.getDeclaredMethod("invoke", types); + return AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public Method run() throws Exception { + Class t = getTrampolineClass(); + Class[] types = { + Method.class, Object.class, Object[].class + }; + Method b = t.getDeclaredMethod("invoke", types); ((AccessibleObject)b).setAccessible(true); return b; } @@ -298,7 +297,6 @@ } catch (Exception e) { throw new InternalError("bouncer cannot be found"); } - return tramp; } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/rmi/log/ReliableLog.java --- a/jdk/src/share/classes/sun/rmi/log/ReliableLog.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/rmi/log/ReliableLog.java Tue Mar 11 23:37:02 2008 -0700 @@ -140,8 +140,8 @@ throws IOException { super(); - this.Debug = ((Boolean) AccessController.doPrivileged( - new GetBooleanAction("sun.rmi.log.debug"))).booleanValue(); + this.Debug = AccessController.doPrivileged( + new GetBooleanAction("sun.rmi.log.debug")).booleanValue(); dir = new File(dirPath); if (!(dir.exists() && dir.isDirectory())) { // create directory @@ -333,8 +333,8 @@ private static Constructor getLogClassConstructor() { - String logClassName = ((String) AccessController.doPrivileged( - new GetPropertyAction("sun.rmi.log.class"))); + String logClassName = AccessController.doPrivileged( + new GetPropertyAction("sun.rmi.log.class")); if (logClassName != null) { try { ClassLoader loader = diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/rmi/registry/RegistryImpl.java --- a/jdk/src/share/classes/sun/rmi/registry/RegistryImpl.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/rmi/registry/RegistryImpl.java Tue Mar 11 23:37:02 2008 -0700 @@ -66,8 +66,10 @@ /* indicate compatibility with JDK 1.1.x version of class */ private static final long serialVersionUID = 4666870661827494597L; - private Hashtable bindings = new Hashtable(101); - private static Hashtable allowedAccessCache = new Hashtable(3); + private Hashtable bindings + = new Hashtable(101); + private static Hashtable allowedAccessCache + = new Hashtable(3); private static RegistryImpl registry; private static ObjID id = new ObjID(ObjID.REGISTRY_ID); @@ -119,7 +121,7 @@ throws RemoteException, NotBoundException { synchronized (bindings) { - Remote obj = (Remote)bindings.get(name); + Remote obj = bindings.get(name); if (obj == null) throw new NotBoundException(name); return obj; @@ -136,7 +138,7 @@ { checkAccess("Registry.bind"); synchronized (bindings) { - Remote curr = (Remote)bindings.get(name); + Remote curr = bindings.get(name); if (curr != null) throw new AlreadyBoundException(name); bindings.put(name, obj); @@ -153,7 +155,7 @@ { checkAccess("Registry.unbind"); synchronized (bindings) { - Remote obj = (Remote)bindings.get(name); + Remote obj = bindings.get(name); if (obj == null) throw new NotBoundException(name); bindings.remove(name); @@ -203,10 +205,9 @@ InetAddress clientHost; try { - clientHost = (InetAddress) - java.security.AccessController.doPrivileged( - new java.security.PrivilegedExceptionAction() { - public Object run() + clientHost = java.security.AccessController.doPrivileged( + new java.security.PrivilegedExceptionAction() { + public InetAddress run() throws java.net.UnknownHostException { return InetAddress.getByName(clientHostName); @@ -228,8 +229,8 @@ final InetAddress finalClientHost = clientHost; java.security.AccessController.doPrivileged( - new java.security.PrivilegedExceptionAction() { - public Object run() throws java.io.IOException { + new java.security.PrivilegedExceptionAction() { + public Void run() throws java.io.IOException { /* * if a ServerSocket can be bound to the client's * address then that address must be local diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/rmi/rmic/RemoteClass.java --- a/jdk/src/share/classes/sun/rmi/rmic/RemoteClass.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/rmi/rmic/RemoteClass.java Tue Mar 11 23:37:02 2008 -0700 @@ -103,7 +103,7 @@ * in the array). */ public ClassDefinition[] getRemoteInterfaces() { - return (ClassDefinition[]) remoteInterfaces.clone(); + return remoteInterfaces.clone(); } /** @@ -118,7 +118,7 @@ * stub/skeleton protocol. */ public Method[] getRemoteMethods() { - return (Method[]) remoteMethods.clone(); + return remoteMethods.clone(); } /** @@ -204,8 +204,8 @@ * chain, add each directly-implemented interface that * somehow extends Remote to a list. */ - Vector remotesImplemented = // list of remote interfaces found - new Vector(); + Vector remotesImplemented = // list of remote interfaces found + new Vector(); for (ClassDefinition classDef = implClassDef; classDef != null;) { @@ -307,13 +307,13 @@ * Now we collect the methods from all of the remote interfaces * into a hashtable. */ - Hashtable methods = new Hashtable(); + Hashtable methods = new Hashtable(); boolean errors = false; - for (Enumeration enumeration = remotesImplemented.elements(); + for (Enumeration enumeration + = remotesImplemented.elements(); enumeration.hasMoreElements();) { - ClassDefinition interfaceDef = - (ClassDefinition) enumeration.nextElement(); + ClassDefinition interfaceDef = enumeration.nextElement(); if (!collectRemoteMethods(interfaceDef, methods)) errors = true; } @@ -336,10 +336,10 @@ */ String[] orderedKeys = new String[methods.size()]; int count = 0; - for (Enumeration enumeration = methods.elements(); + for (Enumeration enumeration = methods.elements(); enumeration.hasMoreElements();) { - Method m = (Method) enumeration.nextElement(); + Method m = enumeration.nextElement(); String key = m.getNameAndDescriptor(); int i; for (i = count; i > 0; --i) { @@ -353,7 +353,7 @@ } remoteMethods = new Method[methods.size()]; for (int i = 0; i < remoteMethods.length; i++) { - remoteMethods[i] = (Method) methods.get(orderedKeys[i]); + remoteMethods[i] = methods.get(orderedKeys[i]); /***** */ if (env.verbose()) { System.out.print("[found remote method <" + i + ">: " + @@ -388,7 +388,7 @@ * or false if an error occurred. */ private boolean collectRemoteMethods(ClassDefinition interfaceDef, - Hashtable table) + Hashtable table) { if (!interfaceDef.isInterface()) { throw new Error( @@ -529,7 +529,7 @@ * the new method (see bugid 4070653). */ String key = newMethod.getNameAndDescriptor(); - Method oldMethod = (Method) table.get(key); + Method oldMethod = table.get(key); if (oldMethod != null) { newMethod = newMethod.mergeWith(oldMethod); if (newMethod == null) { @@ -684,7 +684,7 @@ * methods that can be legally thrown in each of them. */ public ClassDeclaration[] getExceptions() { - return (ClassDeclaration[]) exceptions.clone(); + return exceptions.clone(); } /** @@ -789,7 +789,8 @@ getNameAndDescriptor()); } - Vector legalExceptions = new Vector(); + Vector legalExceptions + = new Vector(); try { collectCompatibleExceptions( other.exceptions, exceptions, legalExceptions); @@ -814,7 +815,7 @@ */ private void collectCompatibleExceptions(ClassDeclaration[] from, ClassDeclaration[] with, - Vector list) + Vector list) throws ClassNotFound { for (int i = 0; i < from.length; i++) { diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/rmi/rmic/newrmic/jrmp/RemoteClass.java --- a/jdk/src/share/classes/sun/rmi/rmic/newrmic/jrmp/RemoteClass.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/rmi/rmic/newrmic/jrmp/RemoteClass.java Tue Mar 11 23:37:02 2008 -0700 @@ -121,7 +121,7 @@ * in the array). **/ ClassDoc[] remoteInterfaces() { - return (ClassDoc[]) remoteInterfaces.clone(); + return remoteInterfaces.clone(); } /** @@ -136,7 +136,7 @@ * stub/skeleton protocol. **/ Method[] remoteMethods() { - return (Method[]) remoteMethods.clone(); + return remoteMethods.clone(); } /** @@ -559,7 +559,7 @@ * methods that can be legally thrown by all of them. **/ ClassDoc[] exceptionTypes() { - return (ClassDoc[]) exceptionTypes.clone(); + return exceptionTypes.clone(); } /** diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/rmi/runtime/Log.java --- a/jdk/src/share/classes/sun/rmi/runtime/Log.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/rmi/runtime/Log.java Tue Mar 11 23:37:02 2008 -0700 @@ -71,7 +71,7 @@ private static final LogFactory logFactory; static { boolean useOld = - Boolean.valueOf((String) java.security.AccessController. + Boolean.valueOf(java.security.AccessController. doPrivileged(new sun.security.action.GetPropertyAction( "sun.rmi.log.useOld"))).booleanValue(); @@ -179,17 +179,16 @@ private static class LoggerLog extends Log { /* alternate console handler for RMI loggers */ - private static final Handler alternateConsole = (Handler) + private static final Handler alternateConsole = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { + new java.security.PrivilegedAction() { + public Handler run() { InternalStreamHandler alternate = new InternalStreamHandler(System.err); alternate.setLevel(Level.ALL); return alternate; } - } - ); + }); /** handler to which messages are copied */ private InternalStreamHandler copyHandler = null; @@ -206,8 +205,8 @@ if (level != null){ java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { + new java.security.PrivilegedAction() { + public Void run() { if (!logger.isLoggable(level)) { logger.setLevel(level); } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/rmi/server/LoaderHandler.java --- a/jdk/src/share/classes/sun/rmi/server/LoaderHandler.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/rmi/server/LoaderHandler.java Tue Mar 11 23:37:02 2008 -0700 @@ -70,7 +70,7 @@ /** RMI class loader log level */ static final int logLevel = LogStream.parseLevel( - (String) java.security.AccessController.doPrivileged( + java.security.AccessController.doPrivileged( new GetPropertyAction("sun.rmi.loader.logLevel"))); /* loader system log */ @@ -83,7 +83,7 @@ */ private static String codebaseProperty = null; static { - String prop = (String) java.security.AccessController.doPrivileged( + String prop = java.security.AccessController.doPrivileged( new GetPropertyAction("java.rmi.server.codebase")); if (prop != null && prop.trim().length() > 0) { codebaseProperty = prop; @@ -94,8 +94,8 @@ private static URL[] codebaseURLs = null; /** table of class loaders that use codebase property for annotation */ - private static final Map codebaseLoaders = - Collections.synchronizedMap(new IdentityHashMap(5)); + private static final Map codebaseLoaders = + Collections.synchronizedMap(new IdentityHashMap(5)); static { for (ClassLoader codebaseLoader = ClassLoader.getSystemClassLoader(); codebaseLoader != null; @@ -111,10 +111,12 @@ * references, so this table does not prevent loaders from being * garbage collected. */ - private static final HashMap loaderTable = new HashMap(5); + private static final HashMap loaderTable + = new HashMap(5); /** reference queue for cleared class loader entries */ - private static final ReferenceQueue refQueue = new ReferenceQueue(); + private static final ReferenceQueue refQueue + = new ReferenceQueue(); /* * Disallow anyone from creating one of these. @@ -757,7 +759,7 @@ throws MalformedURLException { synchronized (pathToURLsCache) { - Object[] v = (Object[]) pathToURLsCache.get(path); + Object[] v = pathToURLsCache.get(path); if (v != null) { return ((URL[])v[0]); } @@ -769,13 +771,14 @@ } synchronized (pathToURLsCache) { pathToURLsCache.put(path, - new Object[] {urls, new SoftReference(path)}); + new Object[] {urls, new SoftReference(path)}); } return urls; } /** map from weak(key=string) to [URL[], soft(key)] */ - private static final Map pathToURLsCache = new WeakHashMap(5); + private static final Map pathToURLsCache + = new WeakHashMap(5); /** * Convert an array of URL objects into a corresponding string @@ -853,9 +856,9 @@ * in the table of RMI class loaders. */ LoaderKey key = new LoaderKey(urls, parent); - entry = (LoaderEntry) loaderTable.get(key); + entry = loaderTable.get(key); - if (entry == null || (loader = (Loader) entry.get()) == null) { + if (entry == null || (loader = entry.get()) == null) { /* * If entry was in table but it's weak reference was cleared, * remove it from the table and mark it as explicitly cleared, @@ -876,9 +879,9 @@ * necessary to load classes from its codebase URL path. */ AccessControlContext acc = getLoaderAccessControlContext(urls); - loader = (Loader) java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { + loader = java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Loader run() { return new Loader(urls, parent); } }, acc); @@ -954,7 +957,7 @@ * loader key for the loader so that the mapping can be removed from * the table efficiently when the weak reference is cleared. */ - private static class LoaderEntry extends WeakReference { + private static class LoaderEntry extends WeakReference { public LoaderKey key; @@ -983,10 +986,10 @@ * getAccessControlContext() in the sun.applet.AppletPanel class. */ // begin with permissions granted to all code in current policy - PermissionCollection perms = (PermissionCollection) + PermissionCollection perms = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { + new java.security.PrivilegedAction() { + public PermissionCollection run() { CodeSource codesource = new CodeSource(null, (java.security.cert.Certificate[]) null); Policy p = java.security.Policy.getPolicy(); diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/rmi/server/MarshalInputStream.java --- a/jdk/src/share/classes/sun/rmi/server/MarshalInputStream.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/rmi/server/MarshalInputStream.java Tue Mar 11 23:37:02 2008 -0700 @@ -59,18 +59,20 @@ * as cached at class initialization time. */ private static final boolean useCodebaseOnlyProperty = - ((Boolean) java.security.AccessController.doPrivileged( + java.security.AccessController.doPrivileged( new sun.security.action.GetBooleanAction( - "java.rmi.server.useCodebaseOnly"))).booleanValue(); + "java.rmi.server.useCodebaseOnly")).booleanValue(); /** table to hold sun classes to which access is explicitly permitted */ - protected static Map permittedSunClasses = new HashMap(3); + protected static Map> permittedSunClasses + = new HashMap>(3); /** if true, don't try superclass first in resolveClass() */ private boolean skipDefaultResolveClass = false; /** callbacks to make when done() called: maps Object to Runnable */ - private final Map doneCallbacks = new HashMap(3); + private final Map doneCallbacks + = new HashMap(3); /** * if true, load classes (if not available locally) only from the @@ -130,7 +132,7 @@ * with that key. */ public Runnable getDoneCallback(Object key) { - return (Runnable) doneCallbacks.get(key); // not thread-safe + return doneCallbacks.get(key); // not thread-safe } /** @@ -153,9 +155,9 @@ * the superclass's close method. */ public void done() { - Iterator iter = doneCallbacks.values().iterator(); + Iterator iter = doneCallbacks.values().iterator(); while (iter.hasNext()) { // not thread-safe - Runnable callback = (Runnable) iter.next(); + Runnable callback = iter.next(); callback.run(); } doneCallbacks.clear(); @@ -276,8 +278,7 @@ name = perm.getName(); } - Class resolvedClass = - (Class) permittedSunClasses.get(className); + Class resolvedClass = permittedSunClasses.get(className); // if class not permitted, throw the SecurityException if ((name == null) || diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/rmi/server/MarshalOutputStream.java --- a/jdk/src/share/classes/sun/rmi/server/MarshalOutputStream.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/rmi/server/MarshalOutputStream.java Tue Mar 11 23:37:02 2008 -0700 @@ -64,8 +64,8 @@ super(out); this.useProtocolVersion(protocolVersion); java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { + new java.security.PrivilegedAction() { + public Void run() { enableReplaceObject(true); return null; } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/rmi/server/Util.java --- a/jdk/src/share/classes/sun/rmi/server/Util.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/rmi/server/Util.java Tue Mar 11 23:37:02 2008 -0700 @@ -67,7 +67,7 @@ /** "server" package log level */ static final int logLevel = LogStream.parseLevel( - (String) AccessController.doPrivileged( + AccessController.doPrivileged( new GetPropertyAction("sun.rmi.server.logLevel"))); /** server reference log */ @@ -76,13 +76,13 @@ /** cached value of property java.rmi.server.ignoreStubClasses */ private static final boolean ignoreStubClasses = - ((Boolean) AccessController.doPrivileged( - new GetBooleanAction("java.rmi.server.ignoreStubClasses"))). + AccessController.doPrivileged( + new GetBooleanAction("java.rmi.server.ignoreStubClasses")). booleanValue(); /** cache of impl classes that have no corresponding stub class */ - private static final Map withoutStubs = - Collections.synchronizedMap(new WeakHashMap(11)); + private static final Map, Void> withoutStubs = + Collections.synchronizedMap(new WeakHashMap, Void>(11)); /** parameter types for stub constructor */ private static final Class[] stubConsParamTypes = { RemoteRef.class }; @@ -207,9 +207,9 @@ * @throws NullPointerException if remoteClass is null */ private static Class[] getRemoteInterfaces(Class remoteClass) { - ArrayList list = new ArrayList(); + ArrayList> list = new ArrayList>(); getRemoteInterfaces(list, remoteClass); - return (Class []) list.toArray(new Class[list.size()]); + return list.toArray(new Class[list.size()]); } /** @@ -220,7 +220,7 @@ * any illegal remote interfaces * @throws NullPointerException if the specified class or list is null */ - private static void getRemoteInterfaces(ArrayList list, Class cl) { + private static void getRemoteInterfaces(ArrayList> list, Class cl) { Class superclass = cl.getSuperclass(); if (superclass != null) { getRemoteInterfaces(list, superclass); @@ -254,7 +254,7 @@ * @throws IllegalArgumentException if m is an illegal remote method */ private static void checkMethod(Method m) { - Class[] ex = m.getExceptionTypes(); + Class[] ex = m.getExceptionTypes(); for (int i = 0; i < ex.length; i++) { if (ex[i].isAssignableFrom(RemoteException.class)) return; @@ -283,7 +283,7 @@ * pickle methods */ try { - Class stubcl = + Class stubcl = Class.forName(stubname, false, remoteClass.getClassLoader()); Constructor cons = stubcl.getConstructor(stubConsParamTypes); return (RemoteStub) cons.newInstance(new Object[] { ref }); diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/rmi/server/WeakClassHashMap.java --- a/jdk/src/share/classes/sun/rmi/server/WeakClassHashMap.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/rmi/server/WeakClassHashMap.java Tue Mar 11 23:37:02 2008 -0700 @@ -69,7 +69,7 @@ synchronized (valueCell) { V value = null; if (valueCell.ref != null) { - value = (V) valueCell.ref.get(); + value = valueCell.ref.get(); } if (value == null) { value = computeValue(remoteClass); diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/rmi/transport/DGCClient.java --- a/jdk/src/share/classes/sun/rmi/transport/DGCClient.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/rmi/transport/DGCClient.java Tue Mar 11 23:37:02 2008 -0700 @@ -85,21 +85,21 @@ /** lease duration to request (usually ignored by server) */ private static final long leaseValue = // default 10 minutes - ((Long) AccessController.doPrivileged( + AccessController.doPrivileged( new GetLongAction("java.rmi.dgc.leaseValue", - 600000))).longValue(); + 600000)).longValue(); /** maximum interval between retries of failed clean calls */ private static final long cleanInterval = // default 3 minutes - ((Long) AccessController.doPrivileged( + AccessController.doPrivileged( new GetLongAction("sun.rmi.dgc.cleanInterval", - 180000))).longValue(); + 180000)).longValue(); /** maximum interval between complete garbage collections of local heap */ private static final long gcInterval = // default 1 hour - ((Long) AccessController.doPrivileged( + AccessController.doPrivileged( new GetLongAction("sun.rmi.dgc.client.gcInterval", - 3600000))).longValue(); + 3600000)).longValue(); /** minimum retry count for dirty calls that fail */ private static final int dirtyFailureRetries = 5; @@ -243,7 +243,7 @@ } catch (RemoteException e) { throw new Error("internal error creating DGC stub"); } - renewCleanThread = (Thread) AccessController.doPrivileged( + renewCleanThread = AccessController.doPrivileged( new NewThreadAction(new RenewCleanThread(), "RenewClean-" + endpoint, true)); renewCleanThread.start(); @@ -473,8 +473,9 @@ if (newRenewTime < renewTime) { renewTime = newRenewTime; if (interruptible) { - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + AccessController.doPrivileged( + new PrivilegedAction() { + public Void run() { renewCleanThread.interrupt(); return null; } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/rmi/transport/Target.java --- a/jdk/src/share/classes/sun/rmi/transport/Target.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/rmi/transport/Target.java Tue Mar 11 23:37:02 2008 -0700 @@ -321,7 +321,7 @@ Remote obj = getImpl(); if (obj instanceof Unreferenced) { final Unreferenced unrefObj = (Unreferenced) obj; - final Thread t = (Thread) + final Thread t = java.security.AccessController.doPrivileged( new NewThreadAction(new Runnable() { public void run() { @@ -334,8 +334,8 @@ * for threads that may invoke user code (see bugid 4171278). */ java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { + new java.security.PrivilegedAction() { + public Void run() { t.setContextClassLoader(ccl); return null; } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/rmi/transport/Transport.java --- a/jdk/src/share/classes/sun/rmi/transport/Transport.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/rmi/transport/Transport.java Tue Mar 11 23:37:02 2008 -0700 @@ -53,7 +53,7 @@ static final int logLevel = LogStream.parseLevel(getLogLevel()); private static String getLogLevel() { - return (String) java.security.AccessController.doPrivileged( + return java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("sun.rmi.transport.logLevel")); } @@ -171,8 +171,8 @@ currentTransport.set(this); try { java.security.AccessController.doPrivileged( - new java.security.PrivilegedExceptionAction() { - public Object run() throws IOException { + new java.security.PrivilegedExceptionAction() { + public Void run() throws IOException { checkAcceptPermission(acc); disp.dispatch(impl, call); return null; diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java --- a/jdk/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java Tue Mar 11 23:37:02 2008 -0700 @@ -89,8 +89,8 @@ static { java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { + new java.security.PrivilegedAction() { + public Void run() { ContentLength = Integer.getInteger("CONTENT_LENGTH", 0).intValue(); QueryString = System.getProperty("QUERY_STRING", ""); diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/rmi/transport/proxy/HttpSendSocket.java --- a/jdk/src/share/classes/sun/rmi/transport/proxy/HttpSendSocket.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/rmi/transport/proxy/HttpSendSocket.java Tue Mar 11 23:37:02 2008 -0700 @@ -78,7 +78,7 @@ * property at the moment that the socket was created. */ private String lineSeparator = - (String) java.security.AccessController.doPrivileged( + java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("line.separator")); /** diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/rmi/transport/proxy/RMIMasterSocketFactory.java --- a/jdk/src/share/classes/sun/rmi/transport/proxy/RMIMasterSocketFactory.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/rmi/transport/proxy/RMIMasterSocketFactory.java Tue Mar 11 23:37:02 2008 -0700 @@ -50,7 +50,7 @@ static int logLevel = LogStream.parseLevel(getLogLevel()); private static String getLogLevel() { - return (String) java.security.AccessController.doPrivileged( + return java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("sun.rmi.transport.proxy.logLevel")); } @@ -63,15 +63,15 @@ private static long connectTimeout = getConnectTimeout(); private static long getConnectTimeout() { - return ((Long) java.security.AccessController.doPrivileged( + return java.security.AccessController.doPrivileged( new GetLongAction("sun.rmi.transport.proxy.connectTimeout", - 15000))).longValue(); // default: 15 seconds + 15000)).longValue(); // default: 15 seconds } /** whether to fallback to HTTP on general connect failures */ - private static final boolean eagerHttpFallback = ((Boolean) + private static final boolean eagerHttpFallback = java.security.AccessController.doPrivileged(new GetBooleanAction( - "sun.rmi.transport.proxy.eagerHttpFallback"))).booleanValue(); + "sun.rmi.transport.proxy.eagerHttpFallback")).booleanValue(); /** table of hosts successfully connected to and the factory used */ private Hashtable successTable = new Hashtable(); @@ -100,14 +100,14 @@ try { String proxyHost; - proxyHost = (String) java.security.AccessController.doPrivileged( + proxyHost = java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("http.proxyHost")); if (proxyHost == null) - proxyHost=(String)java.security.AccessController.doPrivileged( + proxyHost = java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("proxyHost")); - Boolean tmp = (Boolean)java.security.AccessController.doPrivileged( + Boolean tmp = java.security.AccessController.doPrivileged( new sun.security.action.GetBooleanAction("java.rmi.server.disableHttp")); if (!tmp.booleanValue() && @@ -178,10 +178,8 @@ try { synchronized (connector) { - Thread t = (Thread) - java.security.AccessController.doPrivileged( - new NewThreadAction(connector, "AsyncConnector", - true)); + Thread t = java.security.AccessController.doPrivileged( + new NewThreadAction(connector, "AsyncConnector", true)); t.start(); try { diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/rmi/transport/tcp/ConnectionMultiplexer.java --- a/jdk/src/share/classes/sun/rmi/transport/tcp/ConnectionMultiplexer.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/rmi/transport/tcp/ConnectionMultiplexer.java Tue Mar 11 23:37:02 2008 -0700 @@ -49,7 +49,7 @@ static int logLevel = LogStream.parseLevel(getLogLevel()); private static String getLogLevel() { - return (String) java.security.AccessController.doPrivileged( + return java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("sun.rmi.transport.tcp.multiplex.logLevel")); } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/security/jgss/GSSManagerImpl.java --- a/jdk/src/share/classes/sun/security/jgss/GSSManagerImpl.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/security/jgss/GSSManagerImpl.java Tue Mar 11 23:37:02 2008 -0700 @@ -83,7 +83,7 @@ public Oid[] getNamesForMech(Oid mech) throws GSSException { MechanismFactory factory = list.getMechFactory(mech); - return (Oid[])factory.getNameTypes().clone(); + return factory.getNameTypes().clone(); } public Oid[] getMechsForName(Oid nameType){ diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/security/jgss/krb5/InitSecContextToken.java --- a/jdk/src/share/classes/sun/security/jgss/krb5/InitSecContextToken.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/security/jgss/krb5/InitSecContextToken.java Tue Mar 11 23:37:02 2008 -0700 @@ -103,8 +103,7 @@ apReq = new KrbApReq(apReqBytes, keys, addr); //debug("\nReceived AP-REQ and authenticated it.\n"); - EncryptionKey sessionKey - = (EncryptionKey) apReq.getCreds().getSessionKey(); + EncryptionKey sessionKey = apReq.getCreds().getSessionKey(); /* System.out.println("\n\nSession key from service ticket is: " + diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/security/ssl/CipherSuite.java --- a/jdk/src/share/classes/sun/security/ssl/CipherSuite.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/security/ssl/CipherSuite.java Tue Mar 11 23:37:02 2008 -0700 @@ -191,7 +191,7 @@ if (s == null) { throw new IllegalArgumentException("Name must not be null"); } - CipherSuite c = (CipherSuite)nameMap.get(s); + CipherSuite c = nameMap.get(s); if ((c == null) || (c.allowed == false)) { throw new IllegalArgumentException("Unsupported ciphersuite " + s); } @@ -395,7 +395,7 @@ } private static synchronized boolean isAvailable(BulkCipher cipher) { - Boolean b = (Boolean)availableCache.get(cipher); + Boolean b = availableCache.get(cipher); if (b == null) { try { SecretKey key = new SecretKeySpec diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/security/ssl/DHCrypt.java --- a/jdk/src/share/classes/sun/security/ssl/DHCrypt.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/security/ssl/DHCrypt.java Tue Mar 11 23:37:02 2008 -0700 @@ -132,8 +132,7 @@ } try { KeyFactory factory = JsseJce.getKeyFactory("DH"); - return (DHPublicKeySpec)factory.getKeySpec - (key, DHPublicKeySpec.class); + return factory.getKeySpec(key, DHPublicKeySpec.class); } catch (Exception e) { throw new RuntimeException(e); } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/security/ssl/JsseJce.java --- a/jdk/src/share/classes/sun/security/ssl/JsseJce.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/security/ssl/JsseJce.java Tue Mar 11 23:37:02 2008 -0700 @@ -343,8 +343,7 @@ } try { KeyFactory factory = JsseJce.getKeyFactory("RSA"); - return (RSAPublicKeySpec)factory.getKeySpec - (key, RSAPublicKeySpec.class); + return factory.getKeySpec(key, RSAPublicKeySpec.class); } catch (Exception e) { throw (RuntimeException)new RuntimeException().initCause(e); } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/security/ssl/ProtocolList.java --- a/jdk/src/share/classes/sun/security/ssl/ProtocolList.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/security/ssl/ProtocolList.java Tue Mar 11 23:37:02 2008 -0700 @@ -98,7 +98,7 @@ protocolNames[i++] = version.name; } } - return (String[])protocolNames.clone(); + return protocolNames.clone(); } public String toString() { diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/security/ssl/SSLSessionImpl.java --- a/jdk/src/share/classes/sun/security/ssl/SSLSessionImpl.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/security/ssl/SSLSessionImpl.java Tue Mar 11 23:37:02 2008 -0700 @@ -458,7 +458,7 @@ + " for Kerberos cipher suites"); } if (peerCerts != null) { - return (X509Certificate [])peerCerts.clone(); + return peerCerts.clone(); } else { throw new SSLPeerUnverifiedException("peer not authenticated"); } @@ -489,7 +489,7 @@ if (peerCerts == null) { throw new SSLPeerUnverifiedException("peer not authenticated"); } - return ((X500Principal)peerCerts[0].getSubjectX500Principal()); + return peerCerts[0].getSubjectX500Principal(); } /** @@ -508,7 +508,7 @@ (KerberosPrincipal)localPrincipal); } return (localCerts == null ? null : - (X500Principal)localCerts[0].getSubjectX500Principal()); + localCerts[0].getSubjectX500Principal()); } /** diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/security/ssl/SessionId.java --- a/jdk/src/share/classes/sun/security/ssl/SessionId.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/security/ssl/SessionId.java Tue Mar 11 23:37:02 2008 -0700 @@ -64,7 +64,7 @@ /** Returns the bytes in the ID. May be an empty array. */ byte [] getId () { - return (byte []) sessionId.clone (); + return sessionId.clone (); } /** Returns the ID as a string */ diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/security/ssl/SunX509KeyManagerImpl.java --- a/jdk/src/share/classes/sun/security/ssl/SunX509KeyManagerImpl.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/security/ssl/SunX509KeyManagerImpl.java Tue Mar 11 23:37:02 2008 -0700 @@ -172,7 +172,7 @@ if (cred == null) { return null; } else { - return (X509Certificate[])cred.certificates.clone(); + return cred.certificates.clone(); } } @@ -255,7 +255,7 @@ String[] aliases; if (issuers == null || issuers.length == 0) { - aliases = (String[])serverAliasCache.get(keyType); + aliases = serverAliasCache.get(keyType); if (aliases == null) { aliases = getServerAliases(keyType, issuers); // Cache the result (positive and negative lookups) @@ -388,7 +388,7 @@ } } - String[] aliasStrings = (String[])aliases.toArray(STRING0); + String[] aliasStrings = aliases.toArray(STRING0); return ((aliasStrings.length == 0) ? null : aliasStrings); } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/security/x509/CertificatePolicySet.java --- a/jdk/src/share/classes/sun/security/x509/CertificatePolicySet.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/security/x509/CertificatePolicySet.java Tue Mar 11 23:37:02 2008 -0700 @@ -87,7 +87,7 @@ DerOutputStream tmp = new DerOutputStream(); for (int i = 0; i < ids.size(); i++) { - ((CertificatePolicyId)ids.elementAt(i)).encode(tmp); + ids.elementAt(i).encode(tmp); } out.write(DerValue.tag_Sequence,tmp); } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/security/x509/X509Cert.java --- a/jdk/src/share/classes/sun/security/x509/X509Cert.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/security/x509/X509Cert.java Tue Mar 11 23:37:02 2008 -0700 @@ -516,7 +516,7 @@ * Null is returned in the case of a partially constructed cert. */ public byte [] getSignedCert () - { return (byte[])signedCert.clone(); } + { return signedCert.clone(); } /** diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/tools/jar/JarVerifierStream.java --- a/jdk/src/share/classes/sun/tools/jar/JarVerifierStream.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/tools/jar/JarVerifierStream.java Tue Mar 11 23:37:02 2008 -0700 @@ -32,7 +32,6 @@ import java.security.cert.Certificate; import java.security.AccessController; import java.security.cert.X509Certificate; -import java.security.Identity; import java.security.PublicKey; import java.security.Principal; import sun.security.provider.SystemIdentity; @@ -49,7 +48,8 @@ public class JarVerifierStream extends ZipInputStream { private JarEntry current; - private Hashtable verified = new Hashtable(); + private Hashtable> verified + = new Hashtable>(); private JarInputStream jis; private sun.tools.jar.Manifest man = null; @@ -120,7 +120,7 @@ if (current != null) { Certificate[] certs = current.getCertificates(); if (certs != null) { - Vector ids = getIds(certs); + Vector ids = getIds(certs); if (ids != null) { verified.put(current.getName(), ids); } @@ -189,7 +189,7 @@ static class CertCache { Certificate [] certs; - Vector ids; + Vector ids; boolean equals(Certificate[] certs) { if (this.certs == null) { @@ -229,21 +229,21 @@ } } - private ArrayList certCache = null; + private ArrayList certCache = null; /** * Returns the Identity vector for the given array of Certificates */ - protected Vector getIds(Certificate[] certs) { + protected Vector getIds(Certificate[] certs) { if (certs == null) return null; if (certCache == null) - certCache = new ArrayList(); + certCache = new ArrayList(); CertCache cc; for (int i = 0; i < certCache.size(); i++) { - cc = (CertCache) certCache.get(i); + cc = certCache.get(i); if (cc.equals(certs)) { return cc.ids; } @@ -265,8 +265,8 @@ new sun.security.x509.X509Cert(encoded); try { AccessController.doPrivileged( - new java.security.PrivilegedExceptionAction() { - public Object run() + new java.security.PrivilegedExceptionAction() { + public Void run() throws java.security.KeyManagementException { id.addCertificate(oldC); @@ -278,7 +278,7 @@ pae.getException(); } if (cc.ids == null) - cc.ids = new Vector(); + cc.ids = new Vector(); cc.ids.addElement(id); } catch (java.security.KeyManagementException kme) { // ignore if we can't create Identity diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/tools/jconsole/MBeansTab.java --- a/jdk/src/share/classes/sun/tools/jconsole/MBeansTab.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/tools/jconsole/MBeansTab.java Tue Mar 11 23:37:02 2008 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2004-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2004-2007 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 @@ -26,6 +26,7 @@ package sun.tools.jconsole; import java.awt.BorderLayout; +import java.awt.EventQueue; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; @@ -42,7 +43,8 @@ @SuppressWarnings("serial") public class MBeansTab extends Tab implements - NotificationListener, PropertyChangeListener, TreeSelectionListener { + NotificationListener, PropertyChangeListener, + TreeSelectionListener, TreeWillExpandListener { private XTree tree; private XSheet sheet; @@ -70,6 +72,7 @@ return sheet; } + @Override public void dispose() { super.dispose(); sheet.dispose(); @@ -79,61 +82,79 @@ return vmPanel.getUpdateInterval(); } - void synchroniseMBeanServerView() { - // Register listener for MBean registration/unregistration - // - try { - getMBeanServerConnection().addNotificationListener( - MBeanServerDelegate.DELEGATE_NAME, - this, - null, - null); - } catch (InstanceNotFoundException e) { - // Should never happen because the MBeanServerDelegate - // is always present in any standard MBeanServer - // - if (JConsole.isDebug()) { - e.printStackTrace(); - } - } catch (IOException e) { - if (JConsole.isDebug()) { - e.printStackTrace(); + private void buildMBeanServerView() { + new SwingWorker, Void>() { + @Override + public Set doInBackground() { + // Register listener for MBean registration/unregistration + // + try { + getMBeanServerConnection().addNotificationListener( + MBeanServerDelegate.DELEGATE_NAME, + MBeansTab.this, + null, + null); + } catch (InstanceNotFoundException e) { + // Should never happen because the MBeanServerDelegate + // is always present in any standard MBeanServer + // + if (JConsole.isDebug()) { + e.printStackTrace(); + } + } catch (IOException e) { + if (JConsole.isDebug()) { + e.printStackTrace(); + } + vmPanel.getProxyClient().markAsDead(); + return null; + } + // Retrieve MBeans from MBeanServer + // + Set mbeans = null; + try { + mbeans = getMBeanServerConnection().queryNames(null, null); + } catch (IOException e) { + if (JConsole.isDebug()) { + e.printStackTrace(); + } + vmPanel.getProxyClient().markAsDead(); + return null; + } + return mbeans; } - vmPanel.getProxyClient().markAsDead(); - return; - } - // Retrieve MBeans from MBeanServer - // - Set newSet = null; - try { - newSet = getMBeanServerConnection().queryNames(null,null); - } catch (IOException e) { - if (JConsole.isDebug()) { - e.printStackTrace(); + @Override + protected void done() { + try { + // Wait for mbsc.queryNames() result + Set mbeans = get(); + // Do not display anything until the new tree has been built + // + tree.setVisible(false); + // Cleanup current tree + // + tree.removeAll(); + // Add MBeans to tree + // + tree.addMBeansToView(mbeans); + // Display the new tree + // + tree.setVisible(true); + } catch (Exception e) { + Throwable t = Utils.getActualException(e); + if (JConsole.isDebug()) { + System.err.println("Problem at MBean tree construction"); + t.printStackTrace(); + } + } } - vmPanel.getProxyClient().markAsDead(); - return; - } - // Cleanup current tree - // - tree.removeAll(); - // Do not display anything until the new tree has been built - // - tree.setVisible(false); - // Add MBeans to tree - // - for (ObjectName mbean : newSet) { - tree.addMBeanToView(mbean); - } - // Display the new tree - // - tree.setVisible(true); + }.execute(); } public MBeanServerConnection getMBeanServerConnection() { return vmPanel.getProxyClient().getMBeanServerConnection(); } + @Override public void update() { // Ping the connection to see if it is still alive. At // some point the ProxyClient class should centralize @@ -160,6 +181,7 @@ tree.getSelectionModel().setSelectionMode( TreeSelectionModel.SINGLE_TREE_SELECTION); tree.addTreeSelectionListener(this); + tree.addTreeWillExpandListener(this); tree.addMouseListener(ml); JScrollPane theScrollPane = new JScrollPane( tree, @@ -177,55 +199,55 @@ add(mainSplit); } - /* notification listener */ - public void handleNotification(Notification notification, Object handback) { - if (notification instanceof MBeanServerNotification) { - ObjectName mbean = - ((MBeanServerNotification) notification).getMBeanName(); - if (notification.getType().equals( - MBeanServerNotification.REGISTRATION_NOTIFICATION)) { - tree.addMBeanToView(mbean); - } else if (notification.getType().equals( - MBeanServerNotification.UNREGISTRATION_NOTIFICATION)) { - tree.delMBeanFromView(mbean); + /* notification listener: handleNotification */ + public void handleNotification( + final Notification notification, Object handback) { + EventQueue.invokeLater(new Runnable() { + public void run() { + if (notification instanceof MBeanServerNotification) { + ObjectName mbean = + ((MBeanServerNotification) notification).getMBeanName(); + if (notification.getType().equals( + MBeanServerNotification.REGISTRATION_NOTIFICATION)) { + tree.addMBeanToView(mbean); + } else if (notification.getType().equals( + MBeanServerNotification.UNREGISTRATION_NOTIFICATION)) { + tree.removeMBeanFromView(mbean); + } + } + } + }); + } + + /* property change listener: propertyChange */ + public void propertyChange(PropertyChangeEvent evt) { + if (JConsoleContext.CONNECTION_STATE_PROPERTY.equals(evt.getPropertyName())) { + boolean connected = (Boolean) evt.getNewValue(); + if (connected) { + buildMBeanServerView(); + } else { + sheet.dispose(); } } } - /* property change listener */ - public void propertyChange(PropertyChangeEvent evt) { - if (evt.getPropertyName() == JConsoleContext.CONNECTION_STATE_PROPERTY) { - boolean connected = (Boolean) evt.getNewValue(); - if (connected) { - workerAdd(new Runnable() { - public void run() { - synchroniseMBeanServerView(); - } - }); - } else { - sheet.dispose(); - } - } - - } - - /* tree selection listener */ + /* tree selection listener: valueChanged */ public void valueChanged(TreeSelectionEvent e) { DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); sheet.displayNode(node); } - - /* tree mouse listener */ + /* tree mouse listener: mousePressed */ private MouseListener ml = new MouseAdapter() { + @Override public void mousePressed(MouseEvent e) { if (e.getClickCount() == 1) { int selRow = tree.getRowForLocation(e.getX(), e.getY()); if (selRow != -1) { TreePath selPath = tree.getPathForLocation(e.getX(), e.getY()); - DefaultMutableTreeNode node = (DefaultMutableTreeNode) - selPath.getLastPathComponent(); + DefaultMutableTreeNode node = + (DefaultMutableTreeNode) selPath.getLastPathComponent(); if (sheet.isMBeanNode(node)) { tree.expandPath(selPath); } @@ -233,4 +255,22 @@ } } }; + + /* tree will expand listener: treeWillExpand */ + public void treeWillExpand(TreeExpansionEvent e) + throws ExpandVetoException { + TreePath path = e.getPath(); + if (!tree.hasBeenExpanded(path)) { + DefaultMutableTreeNode node = + (DefaultMutableTreeNode) path.getLastPathComponent(); + if (sheet.isMBeanNode(node) && !tree.hasMetadataNodes(node)) { + tree.addMetadataNodes(node); + } + } + } + + /* tree will expand listener: treeWillCollapse */ + public void treeWillCollapse(TreeExpansionEvent e) + throws ExpandVetoException { + } } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/tools/jconsole/MemoryPoolStat.java --- a/jdk/src/share/classes/sun/tools/jconsole/MemoryPoolStat.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/tools/jconsole/MemoryPoolStat.java Tue Mar 11 23:37:02 2008 -0700 @@ -22,6 +22,7 @@ * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ + package sun.tools.jconsole; import java.lang.management.MemoryUsage; diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/tools/jconsole/VMPanel.java --- a/jdk/src/share/classes/sun/tools/jconsole/VMPanel.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/tools/jconsole/VMPanel.java Tue Mar 11 23:37:02 2008 -0700 @@ -45,6 +45,7 @@ @SuppressWarnings("serial") public class VMPanel extends JTabbedPane implements PropertyChangeListener { + private ProxyClient proxyClient; private Timer timer; private int updateInterval; @@ -55,12 +56,9 @@ private String password; private String url; private VMInternalFrame vmIF = null; - private static final String windowsLaF = - "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"; - + "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"; private static ArrayList tabInfos = new ArrayList(); - private boolean wasConnected = false; // The everConnected flag keeps track of whether the window can be @@ -76,7 +74,7 @@ // Each VMPanel has its own instance of the JConsolePlugin // A map of JConsolePlugin to the previous SwingWorker - private Map> plugins = null; + private Map> plugins = null; private boolean pluginTabsAdded = false; // Update these only on the EDT @@ -86,11 +84,11 @@ static { tabInfos.add(new TabInfo(OverviewTab.class, OverviewTab.getTabName(), true)); - tabInfos.add(new TabInfo(MemoryTab.class, MemoryTab.getTabName(), true)); - tabInfos.add(new TabInfo(ThreadTab.class, ThreadTab.getTabName(), true)); - tabInfos.add(new TabInfo(ClassTab.class, ClassTab.getTabName(), true)); + tabInfos.add(new TabInfo(MemoryTab.class, MemoryTab.getTabName(), true)); + tabInfos.add(new TabInfo(ThreadTab.class, ThreadTab.getTabName(), true)); + tabInfos.add(new TabInfo(ClassTab.class, ClassTab.getTabName(), true)); tabInfos.add(new TabInfo(SummaryTab.class, SummaryTab.getTabName(), true)); - tabInfos.add(new TabInfo(MBeansTab.class, MBeansTab.getTabName(), true)); + tabInfos.add(new TabInfo(MBeansTab.class, MBeansTab.getTabName(), true)); } public static TabInfo[] getTabInfos() { @@ -101,8 +99,8 @@ this.proxyClient = proxyClient; this.updateInterval = updateInterval; this.hostName = proxyClient.getHostName(); - this.port = proxyClient.getPort(); - this.vmid = proxyClient.getVmid(); + this.port = proxyClient.getPort(); + this.vmid = proxyClient.getVmid(); this.userName = proxyClient.getUserName(); this.password = proxyClient.getPassword(); this.url = proxyClient.getUrl(); @@ -113,7 +111,7 @@ } } - plugins = new LinkedHashMap>(); + plugins = new LinkedHashMap>(); for (JConsolePlugin p : JConsole.getPlugins()) { p.setContext(proxyClient); plugins.put(p, null); @@ -128,10 +126,9 @@ proxyClient.addPropertyChangeListener(this); addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { - if (connectedIconBounds != null - && (e.getModifiers() & MouseEvent.BUTTON1_MASK) != 0 - && connectedIconBounds.contains(e.getPoint())) { + if (connectedIconBounds != null && (e.getModifiers() & MouseEvent.BUTTON1_MASK) != 0 && connectedIconBounds.contains(e.getPoint())) { if (isConnected()) { disconnect(); @@ -145,23 +142,21 @@ }); } - private static Icon connectedIcon16 = - new ImageIcon(VMPanel.class.getResource("resources/connected16.png")); + new ImageIcon(VMPanel.class.getResource("resources/connected16.png")); private static Icon connectedIcon24 = - new ImageIcon(VMPanel.class.getResource("resources/connected24.png")); + new ImageIcon(VMPanel.class.getResource("resources/connected24.png")); private static Icon disconnectedIcon16 = - new ImageIcon(VMPanel.class.getResource("resources/disconnected16.png")); + new ImageIcon(VMPanel.class.getResource("resources/disconnected16.png")); private static Icon disconnectedIcon24 = - new ImageIcon(VMPanel.class.getResource("resources/disconnected24.png")); - + new ImageIcon(VMPanel.class.getResource("resources/disconnected24.png")); private Rectangle connectedIconBounds; // Override to increase right inset for tab area, // in order to reserve space for the connect toggle. public void setUI(TabbedPaneUI ui) { - Insets insets = (Insets)UIManager.getLookAndFeelDefaults().get("TabbedPane.tabAreaInsets"); - insets = (Insets)insets.clone(); + Insets insets = (Insets) UIManager.getLookAndFeelDefaults().get("TabbedPane.tabAreaInsets"); + insets = (Insets) insets.clone(); insets.right += connectedIcon24.getIconWidth() + 8; UIManager.put("TabbedPane.tabAreaInsets", insets); super.setUI(ui); @@ -225,7 +220,7 @@ private Tab instantiate(TabInfo tabInfo) { try { Constructor con = tabInfo.tabClass.getConstructor(VMPanel.class); - return (Tab)con.newInstance(this); + return (Tab) con.newInstance(this); } catch (Exception ex) { System.err.println(ex); return null; @@ -247,10 +242,11 @@ * IT IS USED TO MAKE SOME LOCAL MANIPULATIONS. */ ProxyClient getProxyClient(boolean assertThread) { - if(assertThread) + if (assertThread) { return getProxyClient(); - else + } else { return proxyClient; + } } public ProxyClient getProxyClient() { @@ -294,6 +290,7 @@ startUpdateTimer(); } else { new Thread("VMPanel.connect") { + public void run() { proxyClient.connect(); } @@ -301,68 +298,63 @@ } } - // Call on EDT public void disconnect() { proxyClient.disconnect(); updateFrameTitle(); } - - // Called on EDT public void propertyChange(PropertyChangeEvent ev) { String prop = ev.getPropertyName(); if (prop == CONNECTION_STATE_PROPERTY) { - ConnectionState oldState = (ConnectionState)ev.getOldValue(); - ConnectionState newState = (ConnectionState)ev.getNewValue(); + ConnectionState oldState = (ConnectionState) ev.getOldValue(); + ConnectionState newState = (ConnectionState) ev.getNewValue(); switch (newState) { - case CONNECTING: - onConnecting(); - break; + case CONNECTING: + onConnecting(); + break; - case CONNECTED: - if (progressBar != null) { - progressBar.setIndeterminate(false); - progressBar.setValue(100); - } - closeOptionPane(); - updateFrameTitle(); - // create tabs if not done - createPluginTabs(); - repaint(); - // Notify tabs - fireConnectedChange(true); - // Enable/disable tabs on initial update - initialUpdate = true; - // Start/Restart update timer on connect/reconnect - startUpdateTimer(); - break; + case CONNECTED: + if (progressBar != null) { + progressBar.setIndeterminate(false); + progressBar.setValue(100); + } + closeOptionPane(); + updateFrameTitle(); + // create tabs if not done + createPluginTabs(); + repaint(); + // Notify tabs + fireConnectedChange(true); + // Enable/disable tabs on initial update + initialUpdate = true; + // Start/Restart update timer on connect/reconnect + startUpdateTimer(); + break; - case DISCONNECTED: - if (progressBar != null) { - progressBar.setIndeterminate(false); - progressBar.setValue(0); - closeOptionPane(); - } - vmPanelDied(); - if (oldState == ConnectionState.CONNECTED) { - // Notify tabs - fireConnectedChange(false); - } - break; + case DISCONNECTED: + if (progressBar != null) { + progressBar.setIndeterminate(false); + progressBar.setValue(0); + closeOptionPane(); + } + vmPanelDied(); + if (oldState == ConnectionState.CONNECTED) { + // Notify tabs + fireConnectedChange(false); + } + break; } } } - - // Called on EDT private void onConnecting() { time0 = System.currentTimeMillis(); - final JConsole jc = (JConsole)SwingUtilities.getWindowAncestor(this); + final JConsole jc = (JConsole) SwingUtilities.getWindowAncestor(this); String connectionName = getConnectionName(); progressBar = new JProgressBar(); @@ -373,17 +365,16 @@ Object[] message = { "

    " + getText("connectingTo1", connectionName) + "

    ", progressPanel, - "" + getText("connectingTo2", connectionName) + "" + "" + getText("connectingTo2", connectionName) + "" }; - optionPane = - SheetDialog.showOptionDialog(this, - message, - JOptionPane.DEFAULT_OPTION, - JOptionPane.INFORMATION_MESSAGE, null, - new String[] { getText("Cancel") }, - 0); + SheetDialog.showOptionDialog(this, + message, + JOptionPane.DEFAULT_OPTION, + JOptionPane.INFORMATION_MESSAGE, null, + new String[]{getText("Cancel")}, + 0); } @@ -398,10 +389,11 @@ try { sleep(2000 - elapsed); } catch (InterruptedException ex) { - // Ignore + // Ignore } } SwingUtilities.invokeLater(new Runnable() { + public void run() { optionPane.setVisible(false); progressBar = null; @@ -425,8 +417,8 @@ private VMInternalFrame getFrame() { if (vmIF == null) { - vmIF = (VMInternalFrame)SwingUtilities.getAncestorOfClass(VMInternalFrame.class, - this); + vmIF = (VMInternalFrame) SwingUtilities.getAncestorOfClass(VMInternalFrame.class, + this); } return vmIF; } @@ -452,27 +444,27 @@ timer.cancel(); } TimerTask timerTask = new TimerTask() { + public void run() { update(); } }; - String timerName = "Timer-"+getConnectionName(); + String timerName = "Timer-" + getConnectionName(); timer = new Timer(timerName, true); timer.schedule(timerTask, 0, updateInterval); } - // Call on EDT private void vmPanelDied() { disconnect(); - final JConsole jc = (JConsole)SwingUtilities.getWindowAncestor(this); + final JConsole jc = (JConsole) SwingUtilities.getWindowAncestor(this); JOptionPane optionPane; - final String connectStr = getText("Connect"); + final String connectStr = getText("Connect"); final String reconnectStr = getText("Reconnect"); - final String cancelStr = getText("Cancel"); + final String cancelStr = getText("Cancel"); String msgTitle, msgExplanation, buttonStr; @@ -488,15 +480,16 @@ } optionPane = - SheetDialog.showOptionDialog(this, - "

    " + msgTitle + "

    " + - "" + msgExplanation + "", - JOptionPane.DEFAULT_OPTION, - JOptionPane.WARNING_MESSAGE, null, - new String[] { buttonStr, cancelStr }, - 0); + SheetDialog.showOptionDialog(this, + "

    " + msgTitle + "

    " + + "" + msgExplanation + "", + JOptionPane.DEFAULT_OPTION, + JOptionPane.WARNING_MESSAGE, null, + new String[]{buttonStr, cancelStr}, + 0); optionPane.addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent event) { if (event.getPropertyName().equals(JOptionPane.VALUE_PROPERTY)) { Object value = event.getNewValue(); @@ -507,7 +500,7 @@ try { getFrame().setClosed(true); } catch (PropertyVetoException ex) { - // Should not happen, but can be ignored. + // Should not happen, but can be ignored. } } } @@ -518,11 +511,13 @@ // Note: This method is called on a TimerTask thread. Any GUI manipulation // must be performed with invokeLater() or invokeAndWait(). private Object lockObject = new Object(); + private void update() { - synchronized(lockObject) { + synchronized (lockObject) { if (!isConnected()) { if (wasConnected) { EventQueue.invokeLater(new Runnable() { + public void run() { vmPanelDied(); } @@ -548,6 +543,7 @@ // if (initialUpdate) { EventQueue.invokeLater(new Runnable() { + public void run() { setEnabledAt(index, true); } @@ -569,8 +565,8 @@ // plugin GUI update for (JConsolePlugin p : plugins.keySet()) { - SwingWorker sw = p.newSwingWorker(); - SwingWorker prevSW = plugins.get(p); + SwingWorker sw = p.newSwingWorker(); + SwingWorker prevSW = plugins.get(p); // schedule SwingWorker to run only if the previous // SwingWorker has finished its task and it hasn't started. if (prevSW == null || prevSW.isDone()) { @@ -583,7 +579,7 @@ } } - // Set the first enabled tab in the tab´s list + // Set the first enabled tab in the tab's list // as the selected tab on initial update // if (initialUpdate) { @@ -622,7 +618,6 @@ return url; } - public String getPassword() { return password; } @@ -636,6 +631,7 @@ } static class TabInfo { + Class tabClass; String name; boolean tabVisible; diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/tools/jconsole/inspector/OperationEntry.java --- a/jdk/src/share/classes/sun/tools/jconsole/inspector/OperationEntry.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/OperationEntry.java Tue Mar 11 23:37:02 2008 -0700 @@ -22,9 +22,9 @@ * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ + package sun.tools.jconsole.inspector; - // java import import java.awt.*; import java.awt.event.*; diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/tools/jconsole/inspector/TableSorter.java --- a/jdk/src/share/classes/sun/tools/jconsole/inspector/TableSorter.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/TableSorter.java Tue Mar 11 23:37:02 2008 -0700 @@ -22,6 +22,7 @@ * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ + package sun.tools.jconsole.inspector; import java.util.*; diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/tools/jconsole/inspector/ThreadDialog.java --- a/jdk/src/share/classes/sun/tools/jconsole/inspector/ThreadDialog.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/ThreadDialog.java Tue Mar 11 23:37:02 2008 -0700 @@ -22,6 +22,7 @@ * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ + package sun.tools.jconsole.inspector; // java import diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/tools/jconsole/inspector/Utils.java --- a/jdk/src/share/classes/sun/tools/jconsole/inspector/Utils.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/Utils.java Tue Mar 11 23:37:02 2008 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2004-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,55 +29,51 @@ import java.lang.reflect.*; import java.math.BigDecimal; import java.math.BigInteger; +import java.util.*; +import java.util.concurrent.ExecutionException; import javax.management.*; import javax.management.openmbean.*; import javax.swing.*; import javax.swing.text.*; -import java.util.*; public class Utils { private Utils() { } - private static Set tableNavigationKeys = - new HashSet(Arrays.asList(new Integer[] { + new HashSet(Arrays.asList(new Integer[]{ KeyEvent.VK_TAB, KeyEvent.VK_ENTER, KeyEvent.VK_HOME, KeyEvent.VK_END, KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT, KeyEvent.VK_UP, KeyEvent.VK_DOWN, - KeyEvent.VK_PAGE_UP, KeyEvent.VK_PAGE_DOWN})); - + KeyEvent.VK_PAGE_UP, KeyEvent.VK_PAGE_DOWN + })); private static final Set> primitiveWrappers = - new HashSet>(Arrays.asList(new Class[] { + new HashSet>(Arrays.asList(new Class[]{ Byte.class, Short.class, Integer.class, Long.class, - Float.class, Double.class, Character.class, Boolean.class})); - + Float.class, Double.class, Character.class, Boolean.class + })); private static final Set> primitives = new HashSet>(); - private static final Map> primitiveMap = new HashMap>(); - private static final Map> primitiveToWrapper = new HashMap>(); - private static final Set editableTypes = new HashSet(); - private static final Set> extraEditableClasses = - new HashSet>(Arrays.asList(new Class[] { + new HashSet>(Arrays.asList(new Class[]{ BigDecimal.class, BigInteger.class, Number.class, - String.class, ObjectName.class})); - + String.class, ObjectName.class + })); private static final Set numericalTypes = new HashSet(); - private static final Set extraNumericalTypes = - new HashSet(Arrays.asList(new String[] { + new HashSet(Arrays.asList(new String[]{ BigDecimal.class.getName(), BigInteger.class.getName(), - Number.class.getName()})); - + Number.class.getName() + })); private static final Set booleanTypes = - new HashSet(Arrays.asList(new String[] { - Boolean.TYPE.getName(), Boolean.class.getName()})); + new HashSet(Arrays.asList(new String[]{ + Boolean.TYPE.getName(), Boolean.class.getName() + })); static { // compute primitives/primitiveMap/primitiveToWrapper @@ -122,10 +118,11 @@ * It's used to cater for the primitive types. */ public static Class getClass(String className) - throws ClassNotFoundException { + throws ClassNotFoundException { Class c; - if ((c = primitiveMap.get(className)) != null) + if ((c = primitiveMap.get(className)) != null) { return c; + } return Class.forName(className); } @@ -155,7 +152,9 @@ * structure, i.e. a data structure jconsole can render as an array. */ public static boolean canBeRenderedAsArray(Object elem) { - if (isSupportedArray(elem)) return true; + if (isSupportedArray(elem)) { + return true; + } if (elem instanceof Collection) { Collection c = (Collection) elem; if (c.isEmpty()) { @@ -168,7 +167,7 @@ // - Collections of other Java types are handled as arrays // return !isUniformCollection(c, CompositeData.class) && - !isUniformCollection(c, TabularData.class); + !isUniformCollection(c, TabularData.class); } } if (elem instanceof Map) { @@ -239,7 +238,9 @@ */ public static String getReadableClassName(String name) { String className = getArrayClassName(name); - if (className == null) return name; + if (className == null) { + return name; + } int index = name.lastIndexOf("["); StringBuilder brackets = new StringBuilder(className); for (int i = 0; i <= index; i++) { @@ -282,7 +283,7 @@ * Try to create a Java object using a one-string-param constructor. */ public static Object newStringConstructor(String type, String param) - throws Exception { + throws Exception { Constructor c = Utils.getClass(type).getConstructor(String.class); try { return c.newInstance(param); @@ -300,7 +301,7 @@ * Try to convert a string value into a numerical value. */ private static Number createNumberFromStringValue(String value) - throws NumberFormatException { + throws NumberFormatException { final String suffix = value.substring(value.length() - 1); if ("L".equalsIgnoreCase(suffix)) { return Long.valueOf(value.substring(0, value.length() - 1)); @@ -314,17 +315,17 @@ try { return Integer.valueOf(value); } catch (NumberFormatException e) { - // OK: Ignore exception... + // OK: Ignore exception... } try { return Long.valueOf(value); } catch (NumberFormatException e1) { - // OK: Ignore exception... + // OK: Ignore exception... } try { return Double.valueOf(value); } catch (NumberFormatException e2) { - // OK: Ignore exception... + // OK: Ignore exception... } throw new NumberFormatException("Cannot convert string value '" + value + "' into a numerical value"); @@ -337,7 +338,7 @@ * will return an Integer object initialized to 10. */ public static Object createObjectFromString(String type, String value) - throws Exception { + throws Exception { Object result; if (primitiveToWrapper.containsKey(type)) { if (type.equals(Character.TYPE.getName())) { @@ -367,7 +368,7 @@ * into a useful object array for passing into a parameter array. */ public static Object[] getParameters(XTextField[] inputs, String[] params) - throws Exception { + throws Exception { Object result[] = new Object[inputs.length]; Object userInput; for (int i = 0; i < inputs.length; i++) { @@ -388,12 +389,17 @@ * If the exception is wrapped, unwrap it. */ public static Throwable getActualException(Throwable e) { + if (e instanceof ExecutionException) { + e = e.getCause(); + } if (e instanceof MBeanException || e instanceof RuntimeMBeanException || e instanceof RuntimeOperationsException || e instanceof ReflectionException) { Throwable t = e.getCause(); - if (t != null) return t; + if (t != null) { + return t; + } } return e; } @@ -401,6 +407,7 @@ @SuppressWarnings("serial") public static class ReadOnlyTableCellEditor extends DefaultCellEditor { + public ReadOnlyTableCellEditor(JTextField tf) { super(tf); tf.addFocusListener(new Utils.EditFocusAdapter(this)); @@ -409,20 +416,25 @@ } public static class EditFocusAdapter extends FocusAdapter { + private CellEditor editor; + public EditFocusAdapter(CellEditor editor) { this.editor = editor; } + + @Override public void focusLost(FocusEvent e) { editor.stopCellEditing(); } - }; + } public static class CopyKeyAdapter extends KeyAdapter { private static final String defaultEditorKitCopyActionName = DefaultEditorKit.copyAction; private static final String transferHandlerCopyActionName = (String) TransferHandler.getCopyAction().getValue(Action.NAME); + @Override public void keyPressed(KeyEvent e) { // Accept "copy" key strokes KeyStroke ks = KeyStroke.getKeyStroke( @@ -441,6 +453,8 @@ e.consume(); } } + + @Override public void keyTyped(KeyEvent e) { e.consume(); } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/tools/jconsole/inspector/XDataViewer.java --- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XDataViewer.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XDataViewer.java Tue Mar 11 23:37:02 2008 -0700 @@ -22,6 +22,7 @@ * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ + package sun.tools.jconsole.inspector; import javax.swing.JTable; @@ -108,6 +109,7 @@ public Component createOperationViewer(Object value, XMBean mbean) { if(value instanceof Number) return null; + if(value instanceof Component) return (Component) value; return createAttributeViewer(value, mbean, null, null); } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/tools/jconsole/inspector/XMBean.java --- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XMBean.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XMBean.java Tue Mar 11 23:37:02 2008 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2004-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2004-2007 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 @@ -28,47 +28,56 @@ import java.io.IOException; import javax.management.*; import javax.swing.Icon; +import sun.tools.jconsole.JConsole; import sun.tools.jconsole.MBeansTab; -public class XMBean extends Object { - private ObjectName objectName; +public class XMBean { + + private final MBeansTab mbeansTab; + private final ObjectName objectName; private Icon icon; private String text; - private boolean broadcaster; + private Boolean broadcaster; + private final Object broadcasterLock = new Object(); private MBeanInfo mbeanInfo; - private MBeansTab mbeansTab; + private final Object mbeanInfoLock = new Object(); - public XMBean(ObjectName objectName, MBeansTab mbeansTab) - throws InstanceNotFoundException, IntrospectionException, - ReflectionException, IOException { + public XMBean(ObjectName objectName, MBeansTab mbeansTab) { this.mbeansTab = mbeansTab; - setObjectName(objectName); + this.objectName = objectName; + text = objectName.getKeyProperty("name"); + if (text == null) { + text = objectName.getDomain(); + } if (MBeanServerDelegate.DELEGATE_NAME.equals(objectName)) { icon = IconManager.MBEANSERVERDELEGATE; } else { icon = IconManager.MBEAN; } - this.broadcaster = isBroadcaster(objectName); - this.mbeanInfo = getMBeanInfo(objectName); } MBeanServerConnection getMBeanServerConnection() { return mbeansTab.getMBeanServerConnection(); } - public boolean isBroadcaster() { - return broadcaster; - } - - private boolean isBroadcaster(ObjectName name) { - try { - return getMBeanServerConnection().isInstanceOf( - name, "javax.management.NotificationBroadcaster"); - } catch (Exception e) { - System.out.println("Error calling isBroadcaster: " + - e.getMessage()); + public Boolean isBroadcaster() { + synchronized (broadcasterLock) { + if (broadcaster == null) { + try { + broadcaster = getMBeanServerConnection().isInstanceOf( + getObjectName(), + "javax.management.NotificationBroadcaster"); + } catch (Exception e) { + if (JConsole.isDebug()) { + System.err.println("Couldn't check if MBean [" + + objectName + "] is a notification broadcaster"); + e.printStackTrace(); + } + return false; + } + } + return broadcaster; } - return false; } public Object invoke(String operationName) throws Exception { @@ -78,35 +87,35 @@ } public Object invoke(String operationName, Object params[], String sig[]) - throws Exception { + throws Exception { Object result = getMBeanServerConnection().invoke( getObjectName(), operationName, params, sig); return result; } public void setAttribute(Attribute attribute) - throws AttributeNotFoundException, InstanceNotFoundException, + throws AttributeNotFoundException, InstanceNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException, IOException { getMBeanServerConnection().setAttribute(getObjectName(), attribute); } public Object getAttribute(String attributeName) - throws AttributeNotFoundException, InstanceNotFoundException, + throws AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException, IOException { return getMBeanServerConnection().getAttribute( getObjectName(), attributeName); } public AttributeList getAttributes(String attributeNames[]) - throws AttributeNotFoundException, InstanceNotFoundException, + throws AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException, IOException { return getMBeanServerConnection().getAttributes( getObjectName(), attributeNames); } public AttributeList getAttributes(MBeanAttributeInfo attributeNames[]) - throws AttributeNotFoundException, InstanceNotFoundException, + throws AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException, IOException { String attributeString[] = new String[attributeNames.length]; for (int i = 0; i < attributeNames.length; i++) { @@ -119,32 +128,34 @@ return objectName; } - private void setObjectName(ObjectName objectName) { - this.objectName = objectName; - // generate a readable name now - String name = getObjectName().getKeyProperty("name"); - if (name == null) - setText(getObjectName().getDomain()); - else - setText(name); + public MBeanInfo getMBeanInfo() throws InstanceNotFoundException, + IntrospectionException, ReflectionException, IOException { + synchronized (mbeanInfoLock) { + if (mbeanInfo == null) { + mbeanInfo = getMBeanServerConnection().getMBeanInfo(objectName); + } + return mbeanInfo; + } } - public MBeanInfo getMBeanInfo() { - return mbeanInfo; + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (obj == this) { + return true; + } + if (!(obj instanceof XMBean)) { + return false; + } + XMBean that = (XMBean) obj; + return getObjectName().equals(that.getObjectName()); } - private MBeanInfo getMBeanInfo(ObjectName name) - throws InstanceNotFoundException, IntrospectionException, - ReflectionException, IOException { - return getMBeanServerConnection().getMBeanInfo(name); - } - - public boolean equals(Object o) { - if (o instanceof XMBean) { - XMBean mbean = (XMBean) o; - return getObjectName().equals((mbean).getObjectName()); - } - return false; + @Override + public int hashCode() { + return (objectName == null ? 0 : objectName.hashCode()); } public String getText() { @@ -163,6 +174,7 @@ this.icon = icon; } + @Override public String toString() { return getText(); } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/tools/jconsole/inspector/XMBeanInfo.java --- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XMBeanInfo.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XMBeanInfo.java Tue Mar 11 23:37:02 2008 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2004-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2004-2007 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 @@ -35,10 +35,7 @@ import javax.swing.border.TitledBorder; import javax.swing.event.*; import javax.swing.table.*; -import javax.swing.tree.*; -import sun.tools.jconsole.JConsole; import sun.tools.jconsole.Resources; -import sun.tools.jconsole.inspector.XNodeInfo.Type; import static sun.tools.jconsole.Utilities.*; @@ -46,21 +43,20 @@ public class XMBeanInfo extends JPanel { private static final Color lightYellow = new Color(255, 255, 128); - private final int NAME_COLUMN = 0; private final int VALUE_COLUMN = 1; - private final String[] columnNames = { Resources.getText("Name"), Resources.getText("Value") }; - private JTable infoTable = new JTable(); private JTable descTable = new JTable(); private JPanel infoBorderPanel = new JPanel(new BorderLayout()); private JPanel descBorderPanel = new JPanel(new BorderLayout()); private static class ReadOnlyDefaultTableModel extends DefaultTableModel { + + @Override public void setValueAt(Object value, int row, int col) { } } @@ -73,17 +69,18 @@ this.tableRowDividerText = tableRowDividerText; } + @Override public String toString() { return tableRowDividerText; } } - private static MBeanInfoTableCellRenderer renderer = new MBeanInfoTableCellRenderer(); private static class MBeanInfoTableCellRenderer extends DefaultTableCellRenderer { + @Override public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { @@ -92,22 +89,24 @@ if (value instanceof TableRowDivider) { JLabel label = new JLabel(value.toString()); label.setBackground(ensureContrast(lightYellow, - label.getForeground())); + label.getForeground())); label.setOpaque(true); return label; } return comp; } } - private static TableCellEditor editor = new MBeanInfoTableCellEditor(new JTextField()); private static class MBeanInfoTableCellEditor extends Utils.ReadOnlyTableCellEditor { + public MBeanInfoTableCellEditor(JTextField tf) { super(tf); } + + @Override public Component getTableCellEditorComponent( JTable table, Object value, boolean isSelected, int row, int column) { @@ -116,7 +115,7 @@ if (value instanceof TableRowDivider) { JLabel label = new JLabel(value.toString()); label.setBackground(ensureContrast(lightYellow, - label.getForeground())); + label.getForeground())); label.setOpaque(true); return label; } @@ -172,6 +171,7 @@ add(descBorderPanel); } + // Call on EDT public void emptyInfoTable() { DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel(); while (tableModel.getRowCount() > 0) { @@ -179,6 +179,7 @@ } } + // Call on EDT public void emptyDescTable() { DefaultTableModel tableModel = (DefaultTableModel) descTable.getModel(); while (tableModel.getRowCount() > 0) { @@ -186,6 +187,7 @@ } } + // Call on EDT private void addDescriptor(Descriptor desc, String text) { if (desc != null && desc.getFieldNames().length > 0) { DefaultTableModel tableModel = (DefaultTableModel) descTable.getModel(); @@ -223,6 +225,7 @@ } } + // Call on EDT public void addMBeanInfo(XMBean mbean, MBeanInfo mbeanInfo) { emptyInfoTable(); emptyDescTable(); @@ -263,6 +266,7 @@ tableModel.newDataAvailable(new TableModelEvent(tableModel)); } + // Call on EDT public void addMBeanAttributeInfo(MBeanAttributeInfo mbai) { emptyInfoTable(); emptyDescTable(); @@ -296,6 +300,7 @@ tableModel.newDataAvailable(new TableModelEvent(tableModel)); } + // Call on EDT public void addMBeanOperationInfo(MBeanOperationInfo mboi) { emptyInfoTable(); emptyDescTable(); @@ -343,6 +348,7 @@ tableModel.newDataAvailable(new TableModelEvent(tableModel)); } + // Call on EDT public void addMBeanNotificationInfo(MBeanNotificationInfo mbni) { emptyInfoTable(); emptyDescTable(); @@ -367,6 +373,7 @@ tableModel.newDataAvailable(new TableModelEvent(tableModel)); } + // Call on EDT private void addMBeanConstructorInfo(MBeanConstructorInfo mbci, String text) { DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel(); Object rowData[] = new Object[2]; @@ -383,6 +390,7 @@ tableModel.newDataAvailable(new TableModelEvent(tableModel)); } + // Call on EDT private void addMBeanParameterInfo(MBeanParameterInfo mbpi, String text) { DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel(); Object rowData[] = new Object[2]; @@ -401,91 +409,4 @@ addDescriptor(mbpi.getDescriptor(), text); tableModel.newDataAvailable(new TableModelEvent(tableModel)); } - - public static void loadInfo(DefaultMutableTreeNode root) { - // Retrieve XMBean from XNodeInfo - // - XMBean mbean = (XMBean) ((XNodeInfo) root.getUserObject()).getData(); - // Initialize MBean*Info - // - final MBeanInfo mbeanInfo; - try { - mbeanInfo = mbean.getMBeanInfo(); - } catch (Exception e) { - if (JConsole.isDebug()) { - e.printStackTrace(); - } - return; - } - MBeanAttributeInfo[] ai = mbeanInfo.getAttributes(); - MBeanOperationInfo[] oi = mbeanInfo.getOperations(); - MBeanNotificationInfo[] ni = mbeanInfo.getNotifications(); - // MBeanAttributeInfo node - // - if (ai != null && ai.length > 0) { - DefaultMutableTreeNode attributes = new DefaultMutableTreeNode(); - XNodeInfo attributesUO = new XNodeInfo(Type.ATTRIBUTES, mbean, - Resources.getText("Attributes"), null); - attributes.setUserObject(attributesUO); - root.add(attributes); - for (MBeanAttributeInfo mbai : ai) { - DefaultMutableTreeNode attribute = new DefaultMutableTreeNode(); - XNodeInfo attributeUO = new XNodeInfo(Type.ATTRIBUTE, - new Object[] {mbean, mbai}, mbai.getName(), null); - attribute.setUserObject(attributeUO); - attributes.add(attribute); - } - } - // MBeanOperationInfo node - // - if (oi != null && oi.length > 0) { - DefaultMutableTreeNode operations = new DefaultMutableTreeNode(); - XNodeInfo operationsUO = new XNodeInfo(Type.OPERATIONS, mbean, - Resources.getText("Operations"), null); - operations.setUserObject(operationsUO); - root.add(operations); - for (MBeanOperationInfo mboi : oi) { - // Compute the operation's tool tip text: - // "operationname(param1type,param2type,...)" - // - StringBuilder sb = new StringBuilder(); - for (MBeanParameterInfo mbpi : mboi.getSignature()) { - sb.append(mbpi.getType() + ","); - } - String signature = sb.toString(); - if (signature.length() > 0) { - // Remove the trailing ',' - // - signature = signature.substring(0, signature.length() - 1); - } - String toolTipText = mboi.getName() + "(" + signature + ")"; - // Create operation node - // - DefaultMutableTreeNode operation = new DefaultMutableTreeNode(); - XNodeInfo operationUO = new XNodeInfo(Type.OPERATION, - new Object[] {mbean, mboi}, mboi.getName(), toolTipText); - operation.setUserObject(operationUO); - operations.add(operation); - } - } - // MBeanNotificationInfo node - // - if (mbean.isBroadcaster()) { - DefaultMutableTreeNode notifications = new DefaultMutableTreeNode(); - XNodeInfo notificationsUO = new XNodeInfo(Type.NOTIFICATIONS, mbean, - Resources.getText("Notifications"), null); - notifications.setUserObject(notificationsUO); - root.add(notifications); - if (ni != null && ni.length > 0) { - for (MBeanNotificationInfo mbni : ni) { - DefaultMutableTreeNode notification = - new DefaultMutableTreeNode(); - XNodeInfo notificationUO = new XNodeInfo(Type.NOTIFICATION, - mbni, mbni.getName(), null); - notification.setUserObject(notificationUO); - notifications.add(notification); - } - } - } - } } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/tools/jconsole/inspector/XMBeanNotifications.java --- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XMBeanNotifications.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XMBeanNotifications.java Tue Mar 11 23:37:02 2008 -0700 @@ -29,17 +29,13 @@ import javax.swing.event.*; import javax.swing.table.*; import javax.swing.tree.*; -import java.awt.BorderLayout; -import java.awt.GridLayout; import java.awt.Font; import java.text.SimpleDateFormat; -import java.awt.FlowLayout; import java.awt.Component; import java.awt.EventQueue; import java.awt.event.*; -import java.awt.Insets; import java.awt.Dimension; import java.util.*; import java.io.*; @@ -49,45 +45,44 @@ import javax.management.openmbean.CompositeData; import javax.management.openmbean.TabularData; +import sun.tools.jconsole.JConsole; import sun.tools.jconsole.Resources; @SuppressWarnings("serial") public class XMBeanNotifications extends JTable implements NotificationListener { - private final static String[] columnNames = { + private final static String[] columnNames = { Resources.getText("TimeStamp"), Resources.getText("Type"), Resources.getText("UserData"), Resources.getText("SeqNum"), Resources.getText("Message"), Resources.getText("Event"), - Resources.getText("Source")}; - + Resources.getText("Source") + }; private HashMap listeners = - new HashMap(); - private boolean subscribed; + new HashMap(); + private volatile boolean subscribed; private XMBeanNotificationsListener currentListener; public final static String NOTIFICATION_RECEIVED_EVENT = - "jconsole.xnotification.received"; - + "jconsole.xnotification.received"; private List notificationListenersList; - private boolean enabled; - private Font normalFont, boldFont; + private volatile boolean enabled; + private Font normalFont, boldFont; private int rowMinHeight = -1; private TableCellEditor userDataEditor = new UserDataCellEditor(); private NotifMouseListener mouseListener = new NotifMouseListener(); private SimpleDateFormat timeFormater = new SimpleDateFormat("HH:mm:ss:SSS"); - private static TableCellEditor editor = new Utils.ReadOnlyTableCellEditor(new JTextField()); public XMBeanNotifications() { - super(new TableSorter(columnNames,0)); + super(new TableSorter(columnNames, 0)); setColumnSelectionAllowed(false); setRowSelectionAllowed(false); getTableHeader().setReorderingAllowed(false); ArrayList l = - new ArrayList(1); + new ArrayList(1); notificationListenersList = Collections.synchronizedList(l); addMouseListener(mouseListener); @@ -103,20 +98,24 @@ addKeyListener(new Utils.CopyKeyAdapter()); } + // Call on EDT public void cancelCellEditing() { - TableCellEditor editor = getCellEditor(); - if (editor != null) { - editor.cancelCellEditing(); + TableCellEditor tce = getCellEditor(); + if (tce != null) { + tce.cancelCellEditing(); } } + // Call on EDT public void stopCellEditing() { - TableCellEditor editor = getCellEditor(); - if (editor != null) { - editor.stopCellEditing(); + TableCellEditor tce = getCellEditor(); + if (tce != null) { + tce.stopCellEditing(); } } + // Call on EDT + @Override public boolean isCellEditable(int row, int col) { UserDataCell cell = getUserDataCell(row, col); if (cell != null) { @@ -125,16 +124,21 @@ return true; } + // Call on EDT + @Override public void setValueAt(Object value, int row, int column) { } - public synchronized Component prepareRenderer(TableCellRenderer renderer, - int row, int column) { + // Call on EDT + @Override + public synchronized Component prepareRenderer( + TableCellRenderer renderer, int row, int column) { //In case we have a repaint thread that is in the process of //repainting an obsolete table, just ignore the call. //It can happen when MBean selection is switched at a very quick rate - if(row >= getRowCount()) + if (row >= getRowCount()) { return null; + } Component comp = super.prepareRenderer(renderer, row, column); @@ -146,9 +150,10 @@ if (column == 2 && cell != null) { comp.setFont(boldFont); int size = cell.getHeight(); - if(size > 0) { - if(getRowHeight(row) != size) + if (size > 0) { + if (getRowHeight(row) != size) { setRowHeight(row, size); + } } } else { comp.setFont(normalFont); @@ -157,34 +162,35 @@ return comp; } - public synchronized TableCellRenderer getCellRenderer(int row, - int column) { + // Call on EDT + @Override + public synchronized TableCellRenderer getCellRenderer(int row, int column) { //In case we have a repaint thread that is in the process of //repainting an obsolete table, just ignore the call. //It can happen when MBean selection is switched at a very quick rate - if(row >= getRowCount()) + if (row >= getRowCount()) { return null; + } DefaultTableCellRenderer renderer; String toolTip = null; UserDataCell cell = getUserDataCell(row, column); - if(cell != null && cell.isInited()) { + if (cell != null && cell.isInited()) { renderer = (DefaultTableCellRenderer) cell.getRenderer(); - } - else { - renderer = (DefaultTableCellRenderer) - super.getCellRenderer(row, - column); + } else { + renderer = + (DefaultTableCellRenderer) super.getCellRenderer(row, column); } - if(cell != null) - toolTip = Resources.getText("Double click to expand/collapse")+". " - + cell.toString(); - else { + if (cell != null) { + toolTip = Resources.getText("Double click to expand/collapse") + + ". " + cell.toString(); + } else { Object val = - ((DefaultTableModel) getModel()).getValueAt(row,column); - if(val != null) + ((DefaultTableModel) getModel()).getValueAt(row, column); + if (val != null) { toolTip = val.toString(); + } } renderer.setToolTipText(toolTip); @@ -192,9 +198,12 @@ return renderer; } + // Call on EDT private UserDataCell getUserDataCell(int row, int column) { - Object obj = ((DefaultTableModel) getModel()).getValueAt(row,column); - if(obj instanceof UserDataCell) return (UserDataCell) obj; + Object obj = ((DefaultTableModel) getModel()).getValueAt(row, column); + if (obj instanceof UserDataCell) { + return (UserDataCell) obj; + } return null; } @@ -204,19 +213,22 @@ public long getReceivedNotifications(XMBean mbean) { XMBeanNotificationsListener listener = - listeners.get(mbean.getObjectName()); - if(listener == null) return 0; - else + listeners.get(mbean.getObjectName()); + if (listener == null) { + return 0; + } else { return listener.getReceivedNotifications(); + } } public synchronized boolean clearCurrentNotifications() { emptyTable(); - if(currentListener != null) { + if (currentListener != null) { currentListener.clear(); return true; - } else + } else { return false; + } } public synchronized boolean unregisterListener(DefaultMutableTreeNode node) { @@ -225,29 +237,25 @@ } public synchronized void registerListener(DefaultMutableTreeNode node) - throws InstanceNotFoundException, IOException { + throws InstanceNotFoundException, IOException { XMBean mbean = (XMBean) ((XNodeInfo) node.getUserObject()).getData(); - if(!subscribed) { + if (!subscribed) { try { - mbean.getMBeanServerConnection(). - addNotificationListener(new ObjectName("JMImplementation:type=MBeanServerDelegate"), - this, - null, - null); + mbean.getMBeanServerConnection().addNotificationListener( + MBeanServerDelegate.DELEGATE_NAME, this, null, null); subscribed = true; - }catch(Exception e) { - System.out.println("Error adding listener for delegate :"+ - e.getMessage()); + } catch (Exception e) { + if (JConsole.isDebug()) { + System.err.println("Error adding listener for delegate:"); + e.printStackTrace(); + } } } - XMBeanNotificationsListener listener = - listeners.get(mbean.getObjectName()); + listeners.get(mbean.getObjectName()); if (listener == null) { - listener = new XMBeanNotificationsListener(this, - mbean, - node, - columnNames); + listener = new XMBeanNotificationsListener( + this, mbean, node, columnNames); listeners.put(mbean.getObjectName(), listener); } else { if (!listener.isRegistered()) { @@ -259,19 +267,21 @@ currentListener = listener; } - public synchronized void handleNotification(Notification notif, - Object handback) { + public synchronized void handleNotification( + Notification notif, Object handback) { try { if (notif instanceof MBeanServerNotification) { ObjectName mbean = - ((MBeanServerNotification)notif).getMBeanName(); - if (notif.getType().indexOf("JMX.mbean.unregistered")>=0){ + ((MBeanServerNotification) notif).getMBeanName(); + if (notif.getType().indexOf("JMX.mbean.unregistered") >= 0) { unregister(mbean); } } - } catch(Exception e) { - System.out.println("Error unregistering notification:"+ - e.getMessage()); + } catch (Exception e) { + if (JConsole.isDebug()) { + System.err.println("Error unregistering notification:"); + e.printStackTrace(); + } } } @@ -283,75 +293,77 @@ private synchronized boolean unregister(ObjectName mbean) { XMBeanNotificationsListener listener = listeners.get(mbean); - if(listener != null && listener.isRegistered()) { + if (listener != null && listener.isRegistered()) { listener.unregister(); return true; - } else + } else { return false; + } } public void addNotificationsListener(NotificationListener nl) { - notificationListenersList.add(nl); + notificationListenersList.add(nl); } public void removeNotificationsListener(NotificationListener nl) { notificationListenersList.remove(nl); } - void fireNotificationReceived(XMBeanNotificationsListener listener, - XMBean mbean, - DefaultMutableTreeNode node, - Object[] rowData, - long received) { - if(enabled) { + // Call on EDT + void fireNotificationReceived( + XMBeanNotificationsListener listener, XMBean mbean, + DefaultMutableTreeNode node, Object[] rowData, long received) { + if (enabled) { DefaultTableModel tableModel = (DefaultTableModel) getModel(); - if(listener == currentListener) { - - //tableModel.addRow(rowData); + if (listener == currentListener) { tableModel.insertRow(0, rowData); - - //tableModel.newDataAvailable(new TableModelEvent(tableModel)); repaint(); } } - - Notification notif = new Notification(NOTIFICATION_RECEIVED_EVENT, - this, - 0); - notif.setUserData(new Long(received)); - for(NotificationListener nl : notificationListenersList) - nl.handleNotification(notif,node); + Notification notif = + new Notification(NOTIFICATION_RECEIVED_EVENT, this, 0); + notif.setUserData(received); + for (NotificationListener nl : notificationListenersList) { + nl.handleNotification(notif, node); + } } + // Call on EDT private void updateModel(List data) { emptyTable(); DefaultTableModel tableModel = (DefaultTableModel) getModel(); - for(Object[] rowData : data) + for (Object[] rowData : data) { tableModel.addRow(rowData); + } } public synchronized boolean isListenerRegistered(XMBean mbean) { XMBeanNotificationsListener listener = - listeners.get(mbean.getObjectName()); - if(listener == null) return false; + listeners.get(mbean.getObjectName()); + if (listener == null) { + return false; + } return listener.isRegistered(); } + // Call on EDT public synchronized void loadNotifications(XMBean mbean) { XMBeanNotificationsListener listener = - listeners.get(mbean.getObjectName()); + listeners.get(mbean.getObjectName()); emptyTable(); - if(listener != null ) { + if (listener != null) { enabled = true; List data = listener.getData(); updateModel(data); currentListener = listener; validate(); repaint(); - } else + } else { enabled = false; + } } + // Call on EDT private void setColumnEditors() { TableColumnModel tcm = getColumnModel(); for (int i = 0; i < columnNames.length; i++) { @@ -364,40 +376,40 @@ } } + // Call on EDT public boolean isTableEditable() { return true; } + // Call on EDT public synchronized void emptyTable() { - DefaultTableModel model = (DefaultTableModel)getModel(); + DefaultTableModel model = (DefaultTableModel) getModel(); //invalidate(); - while (model.getRowCount()>0) + while (model.getRowCount() > 0) { model.removeRow(0); + } validate(); } - synchronized void updateUserDataCell(int row, - int col) { + // Call on EDT + synchronized void updateUserDataCell(int row, int col) { Object obj = getModel().getValueAt(row, 2); - if(obj instanceof UserDataCell) { + if (obj instanceof UserDataCell) { UserDataCell cell = (UserDataCell) obj; - if(!cell.isInited()) { - if(rowMinHeight == -1) + if (!cell.isInited()) { + if (rowMinHeight == -1) { rowMinHeight = getRowHeight(row); - - cell.init(super.getCellRenderer(row, col), - rowMinHeight); + } + cell.init(super.getCellRenderer(row, col), rowMinHeight); } cell.switchState(); - setRowHeight(row, - cell.getHeight()); + setRowHeight(row, cell.getHeight()); - if(!cell.isMaximized()) { + if (!cell.isMaximized()) { cancelCellEditing(); //Back to simple editor. - editCellAt(row, - 2); + editCellAt(row, 2); } invalidate(); @@ -406,7 +418,9 @@ } class UserDataCellRenderer extends DefaultTableCellRenderer { + Component comp; + UserDataCellRenderer(Component comp) { this.comp = comp; Dimension d = comp.getPreferredSize(); @@ -415,56 +429,62 @@ } } - public Component getTableCellRendererComponent(JTable table, - Object value, - boolean isSelected, - boolean hasFocus, - int row, - int column) { + @Override + public Component getTableCellRendererComponent( + JTable table, + Object value, + boolean isSelected, + boolean hasFocus, + int row, + int column) { return comp; } public Component getComponent() { return comp; } - } class UserDataCell { + TableCellRenderer minRenderer; UserDataCellRenderer maxRenderer; int minHeight; boolean minimized = true; boolean init = false; Object userData; - UserDataCell(Object userData, Component max) { - this.userData = userData; - this.maxRenderer = new UserDataCellRenderer(max); - } + UserDataCell(Object userData, Component max) { + this.userData = userData; + this.maxRenderer = new UserDataCellRenderer(max); + + } - public String toString() { - if(userData == null) return null; - if(userData.getClass().isArray()) { - String name = - Utils.getArrayClassName(userData.getClass().getName()); - int length = Array.getLength(userData); - return name + "[" + length +"]"; - } + @Override + public String toString() { + if (userData == null) { + return null; + } + if (userData.getClass().isArray()) { + String name = + Utils.getArrayClassName(userData.getClass().getName()); + int length = Array.getLength(userData); + return name + "[" + length + "]"; + } - if(userData instanceof CompositeData || - userData instanceof TabularData) + if (userData instanceof CompositeData || + userData instanceof TabularData) { return userData.getClass().getName(); + } return userData.toString(); - } + } boolean isInited() { return init; } - void init(TableCellRenderer minRenderer, - int minHeight) { + void init(TableCellRenderer minRenderer, int minHeight) { this.minRenderer = minRenderer; this.minHeight = minHeight; init = true; @@ -473,9 +493,11 @@ void switchState() { minimized = !minimized; } + boolean isMaximized() { return !minimized; } + void minimize() { minimized = true; } @@ -485,30 +507,39 @@ } int getHeight() { - if(minimized) return minHeight; - else + if (minimized) { + return minHeight; + } else { return (int) maxRenderer.getComponent(). - getPreferredSize().getHeight() ; + getPreferredSize().getHeight(); + } } TableCellRenderer getRenderer() { - if(minimized) return minRenderer; - else return maxRenderer; + if (minimized) { + return minRenderer; + } else { + return maxRenderer; + } } } class NotifMouseListener extends MouseAdapter { + @Override public void mousePressed(MouseEvent e) { - if(e.getButton() == MouseEvent.BUTTON1) { - if(e.getClickCount() >= 2) { + if (e.getButton() == MouseEvent.BUTTON1) { + if (e.getClickCount() >= 2) { int row = XMBeanNotifications.this.getSelectedRow(); int col = XMBeanNotifications.this.getSelectedColumn(); - if(col != 2) return; - if(col == -1 || row == -1) return; + if (col != 2) { + return; + } + if (col == -1 || row == -1) { + return; + } - XMBeanNotifications.this.updateUserDataCell(row, - col); + XMBeanNotifications.this.updateUserDataCell(row, col); } } } @@ -516,20 +547,21 @@ class UserDataCellEditor extends XTextFieldEditor { // implements javax.swing.table.TableCellEditor - public Component getTableCellEditorComponent(JTable table, - Object value, - boolean isSelected, - int row, - int column) { + @Override + public Component getTableCellEditorComponent( + JTable table, + Object value, + boolean isSelected, + int row, + int column) { Object val = value; - if(column == 2) { - Object obj = getModel().getValueAt(row, - column); - if(obj instanceof UserDataCell) { + if (column == 2) { + Object obj = getModel().getValueAt(row, column); + if (obj instanceof UserDataCell) { UserDataCell cell = (UserDataCell) obj; - if(cell.getRenderer() instanceof UserDataCellRenderer) { + if (cell.getRenderer() instanceof UserDataCellRenderer) { UserDataCellRenderer zr = - (UserDataCellRenderer) cell.getRenderer(); + (UserDataCellRenderer) cell.getRenderer(); return zr.getComponent(); } } else { @@ -539,12 +571,14 @@ return comp; } } - return super.getTableCellEditorComponent(table, - val, - isSelected, - row, - column); + return super.getTableCellEditorComponent( + table, + val, + isSelected, + row, + column); } + @Override public boolean stopCellEditing() { int editingRow = getEditingRow(); @@ -554,7 +588,7 @@ if (obj instanceof UserDataCell) { UserDataCell cell = (UserDataCell) obj; if (cell.isMaximized()) { - this.cancelCellEditing(); + cancelCellEditing(); return true; } } @@ -564,17 +598,20 @@ } class XMBeanNotificationsListener implements NotificationListener { + private String[] columnNames; private XMBean xmbean; private DefaultMutableTreeNode node; - private long received; + private volatile long received; private XMBeanNotifications notifications; - private boolean unregistered; + private volatile boolean unregistered; private ArrayList data = new ArrayList(); - public XMBeanNotificationsListener(XMBeanNotifications notifications, - XMBean xmbean, - DefaultMutableTreeNode node, - String[] columnNames) { + + public XMBeanNotificationsListener( + XMBeanNotifications notifications, + XMBean xmbean, + DefaultMutableTreeNode node, + String[] columnNames) { this.notifications = notifications; this.xmbean = xmbean; this.node = node; @@ -591,22 +628,24 @@ received = 0; } - public boolean isRegistered() { + public synchronized boolean isRegistered() { return !unregistered; } public synchronized void unregister() { try { - xmbean.getMBeanServerConnection(). - removeNotificationListener(xmbean.getObjectName(),this,null,null); - }catch(Exception e) { - System.out.println("Error removing listener :"+ - e.getMessage()); + xmbean.getMBeanServerConnection().removeNotificationListener( + xmbean.getObjectName(), this, null, null); + } catch (Exception e) { + if (JConsole.isDebug()) { + System.err.println("Error removing listener:"); + e.printStackTrace(); + } } unregistered = true; } - public long getReceivedNotifications() { + public synchronized long getReceivedNotifications() { return received; } @@ -614,52 +653,62 @@ clear(); this.node = node; try { - xmbean.getMBeanServerConnection(). - addNotificationListener(xmbean.getObjectName(),this,null,null); + xmbean.getMBeanServerConnection().addNotificationListener( + xmbean.getObjectName(), this, null, null); unregistered = false; - }catch(Exception e) { - System.out.println("Error adding listener :"+ - e.getMessage()); + } catch (Exception e) { + if (JConsole.isDebug()) { + System.err.println("Error adding listener:"); + e.printStackTrace(); + } } } - public synchronized void handleNotification(Notification e, - Object handback) { - try { - if(unregistered) return; - Date receivedDate = new Date(e.getTimeStamp()); - String time = timeFormater.format(receivedDate); + public synchronized void handleNotification( + final Notification n, Object hb) { + EventQueue.invokeLater(new Runnable() { - Object userData = e.getUserData(); - Component comp = null; - UserDataCell cell = null; - if((comp = XDataViewer.createNotificationViewer(userData)) - != null) { - XDataViewer.registerForMouseEvent(comp, mouseListener); - cell = new UserDataCell(userData, comp); - } + public void run() { + synchronized (XMBeanNotificationsListener.this) { + try { + if (unregistered) { + return; + } + Date receivedDate = new Date(n.getTimeStamp()); + String time = timeFormater.format(receivedDate); + + Object userData = n.getUserData(); + Component comp = null; + UserDataCell cell = null; + if ((comp = XDataViewer.createNotificationViewer(userData)) != null) { + XDataViewer.registerForMouseEvent(comp, mouseListener); + cell = new UserDataCell(userData, comp); + } - Object[] rowData = {time, - e.getType(), - (cell == null ? userData : cell), - new Long(e.getSequenceNumber()), - e.getMessage(), - e, - e.getSource()}; - received++; - data.add(0, rowData); + Object[] rowData = { + time, + n.getType(), + (cell == null ? userData : cell), + n.getSequenceNumber(), + n.getMessage(), + n, + n.getSource() + }; + received++; + data.add(0, rowData); - notifications.fireNotificationReceived(this, - xmbean, - node, - rowData, - received); - } - catch (Exception ex) { - ex.printStackTrace(); - System.out.println("Error when handling notification :"+ - ex.toString()); - } + notifications.fireNotificationReceived( + XMBeanNotificationsListener.this, + xmbean, node, rowData, received); + } catch (Exception e) { + if (JConsole.isDebug()) { + System.err.println("Error handling notification:"); + e.printStackTrace(); + } + } + } + } + }); } } } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/tools/jconsole/inspector/XMBeanOperations.java --- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XMBeanOperations.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XMBeanOperations.java Tue Mar 11 23:37:02 2008 -0700 @@ -22,6 +22,7 @@ * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ + package sun.tools.jconsole.inspector; import javax.management.*; diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/tools/jconsole/inspector/XObject.java --- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XObject.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XObject.java Tue Mar 11 23:37:02 2008 -0700 @@ -22,6 +22,7 @@ * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ + package sun.tools.jconsole.inspector; // java import diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/tools/jconsole/inspector/XOperations.java --- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XOperations.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XOperations.java Tue Mar 11 23:37:02 2008 -0700 @@ -33,10 +33,7 @@ import java.awt.GridLayout; import java.awt.FlowLayout; import java.awt.Component; -import java.awt.EventQueue; import java.awt.event.*; -import java.awt.Insets; -import java.awt.Dimension; import java.util.*; import java.io.*; @@ -49,29 +46,30 @@ public abstract class XOperations extends JPanel implements ActionListener { public final static String OPERATION_INVOCATION_EVENT = - "jam.xoperations.invoke.result"; + "jam.xoperations.invoke.result"; private java.util.List notificationListenersList; - private Hashtable operationEntryTable; - private XMBean mbean; private MBeanInfo mbeanInfo; private MBeansTab mbeansTab; + public XOperations(MBeansTab mbeansTab) { - super(new GridLayout(1,1)); + super(new GridLayout(1, 1)); this.mbeansTab = mbeansTab; operationEntryTable = new Hashtable(); ArrayList l = - new ArrayList(1); + new ArrayList(1); notificationListenersList = - Collections.synchronizedList(l); + Collections.synchronizedList(l); } + // Call on EDT public void removeOperations() { removeAll(); } - public void loadOperations(XMBean mbean,MBeanInfo mbeanInfo) { + // Call on EDT + public void loadOperations(XMBean mbean, MBeanInfo mbeanInfo) { this.mbean = mbean; this.mbeanInfo = mbeanInfo; // add operations information @@ -80,131 +78,149 @@ // remove listeners, if any Component listeners[] = getComponents(); - for (int i = 0; i < listeners.length; i++) - if (listeners[i] instanceof JButton) - ((JButton)listeners[i]).removeActionListener(this); + for (int i = 0; i < listeners.length; i++) { + if (listeners[i] instanceof JButton) { + ((JButton) listeners[i]).removeActionListener(this); + } + } removeAll(); setLayout(new BorderLayout()); JButton methodButton; JLabel methodLabel; - JPanel innerPanelLeft,innerPanelRight; - JPanel outerPanelLeft,outerPanelRight; - outerPanelLeft = new JPanel(new GridLayout(operations.length,1)); - outerPanelRight = new JPanel(new GridLayout(operations.length,1)); + JPanel innerPanelLeft, innerPanelRight; + JPanel outerPanelLeft, outerPanelRight; + outerPanelLeft = new JPanel(new GridLayout(operations.length, 1)); + outerPanelRight = new JPanel(new GridLayout(operations.length, 1)); - for (int i=0;i20) { + String returnType = operations[i].getReturnType(); + if (returnType == null) { + methodLabel = new JLabel("null", JLabel.RIGHT); + if (JConsole.isDebug()) { + System.err.println( + "WARNING: The operation's return type " + + "shouldn't be \"null\". Check how the " + + "MBeanOperationInfo for the \"" + + operations[i].getName() + "\" operation has " + + "been defined in the MBean's implementation code."); + } + } else { + methodLabel = new JLabel( + Utils.getReadableClassName(returnType), JLabel.RIGHT); + } + innerPanelLeft.add(methodLabel); + if (methodLabel.getText().length() > 20) { methodLabel.setText(methodLabel.getText(). - substring(methodLabel.getText(). - lastIndexOf(".")+1, - methodLabel.getText().length())); + substring(methodLabel.getText(). + lastIndexOf(".") + 1, + methodLabel.getText().length())); } methodButton = new JButton(operations[i].getName()); methodButton.setToolTipText(operations[i].getDescription()); boolean callable = isCallable(operations[i].getSignature()); - if(callable) + if (callable) { methodButton.addActionListener(this); - else + } else { methodButton.setEnabled(false); + } MBeanParameterInfo[] signature = operations[i].getSignature(); OperationEntry paramEntry = new OperationEntry(operations[i], - callable, - methodButton, - this); + callable, + methodButton, + this); operationEntryTable.put(methodButton, paramEntry); innerPanelRight.add(methodButton); - if(signature.length==0) - innerPanelRight.add(new JLabel("( )",JLabel.CENTER)); - else - innerPanelRight.add(paramEntry); + if (signature.length == 0) { + innerPanelRight.add(new JLabel("( )", JLabel.CENTER)); + } else { + innerPanelRight.add(paramEntry); + } - outerPanelLeft.add(innerPanelLeft,BorderLayout.WEST); - outerPanelRight.add(innerPanelRight,BorderLayout.CENTER); + outerPanelLeft.add(innerPanelLeft, BorderLayout.WEST); + outerPanelRight.add(innerPanelRight, BorderLayout.CENTER); } - add(outerPanelLeft,BorderLayout.WEST); - add(outerPanelRight,BorderLayout.CENTER); + add(outerPanelLeft, BorderLayout.WEST); + add(outerPanelRight, BorderLayout.CENTER); validate(); } private boolean isCallable(MBeanParameterInfo[] signature) { - for(int i = 0; i < signature.length; i++) { - if(!Utils.isEditableType(signature[i].getType())) + for (int i = 0; i < signature.length; i++) { + if (!Utils.isEditableType(signature[i].getType())) { return false; + } } return true; } + // Call on EDT public void actionPerformed(final ActionEvent e) { - performInvokeRequest((JButton)e.getSource()); + performInvokeRequest((JButton) e.getSource()); } void performInvokeRequest(final JButton button) { - mbeansTab.workerAdd(new Runnable() { - public void run() { + final OperationEntry entryIf = operationEntryTable.get(button); + new SwingWorker() { + @Override + public Object doInBackground() throws Exception { + return mbean.invoke(button.getText(), + entryIf.getParameters(), entryIf.getSignature()); + } + @Override + protected void done() { try { - OperationEntry entryIf = operationEntryTable.get(button); - Object result = null; - result = mbean.invoke(button.getText(), - entryIf.getParameters(), - entryIf.getSignature()); + Object result = get(); // sends result notification to upper level if // there is a return value if (entryIf.getReturnType() != null && - !entryIf.getReturnType().equals(Void.TYPE.getName()) && - !entryIf.getReturnType().equals(Void.class.getName())) - fireChangedNotification(OPERATION_INVOCATION_EVENT, - button, - result); - else - EventQueue.invokeLater(new ThreadDialog( + !entryIf.getReturnType().equals(Void.TYPE.getName()) && + !entryIf.getReturnType().equals(Void.class.getName())) { + fireChangedNotification(OPERATION_INVOCATION_EVENT, button, result); + } else { + new ThreadDialog( + button, + Resources.getText("Method successfully invoked"), + Resources.getText("Info"), + JOptionPane.INFORMATION_MESSAGE).run(); + } + } catch (Throwable t) { + t = Utils.getActualException(t); + if (JConsole.isDebug()) { + t.printStackTrace(); + } + new ThreadDialog( button, - Resources.getText("Method successfully invoked"), - Resources.getText("Info"), - JOptionPane.INFORMATION_MESSAGE)); - } catch (Throwable ex) { - if (JConsole.isDebug()) { - ex.printStackTrace(); - } - ex = Utils.getActualException(ex); - String message = ex.toString(); - EventQueue.invokeLater(new ThreadDialog( - button, - Resources.getText("Problem invoking") + " " + - button.getText() + " : " + message, - Resources.getText("Error"), - JOptionPane.ERROR_MESSAGE)); + Resources.getText("Problem invoking") + " " + + button.getText() + " : " + t.toString(), + Resources.getText("Error"), + JOptionPane.ERROR_MESSAGE).run(); } } - }); + }.execute(); } public void addOperationsListener(NotificationListener nl) { - notificationListenersList.add(nl); - } + notificationListenersList.add(nl); + } public void removeOperationsListener(NotificationListener nl) { notificationListenersList.remove(nl); } - private void fireChangedNotification(String type, - Object source, - Object handback) { - Notification e = new Notification(type,source,0); - for(NotificationListener nl : notificationListenersList) - nl.handleNotification(e,handback); + // Call on EDT + private void fireChangedNotification( + String type, Object source, Object handback) { + Notification n = new Notification(type, source, 0); + for (NotificationListener nl : notificationListenersList) { + nl.handleNotification(n, handback); + } } - protected abstract MBeanOperationInfo[] - updateOperations(MBeanOperationInfo[] operations); + protected abstract MBeanOperationInfo[] updateOperations(MBeanOperationInfo[] operations); } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/tools/jconsole/inspector/XPlotter.java --- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XPlotter.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XPlotter.java Tue Mar 11 23:37:02 2008 -0700 @@ -22,7 +22,9 @@ * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ + package sun.tools.jconsole.inspector; + import sun.tools.jconsole.Plotter; import javax.swing.JTable; import java.awt.Graphics; diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/tools/jconsole/inspector/XPlottingViewer.java --- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XPlottingViewer.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XPlottingViewer.java Tue Mar 11 23:37:02 2008 -0700 @@ -22,6 +22,7 @@ * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ + package sun.tools.jconsole.inspector; import java.awt.*; diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/tools/jconsole/inspector/XSheet.java --- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XSheet.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XSheet.java Tue Mar 11 23:37:02 2008 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2004-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2004-2007 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 @@ -28,7 +28,6 @@ import java.awt.*; import java.awt.event.*; import java.io.*; -import java.util.Enumeration; import javax.management.*; import javax.swing.*; import javax.swing.border.*; @@ -45,31 +44,22 @@ private JPanel mainPanel; private JPanel southPanel; - // Node being currently displayed - private DefaultMutableTreeNode node; - + private volatile DefaultMutableTreeNode currentNode; // MBean being currently displayed - private XMBean mbean; - + private volatile XMBean mbean; // XMBeanAttributes container private XMBeanAttributes mbeanAttributes; - // XMBeanOperations container private XMBeanOperations mbeanOperations; - // XMBeanNotifications container private XMBeanNotifications mbeanNotifications; - // XMBeanInfo container private XMBeanInfo mbeanInfo; - // Refresh JButton (mbean attributes case) private JButton refreshButton; - // Subscribe/Unsubscribe/Clear JButton (mbean notifications case) - private JButton clearButton, subscribeButton, unsubscribeButton; - + private JButton clearButton, subscribeButton, unsubscribeButton; // Reference to MBeans tab private MBeansTab mbeansTab; @@ -86,6 +76,7 @@ private void setupScreen() { setLayout(new BorderLayout()); + setBorder(BorderFactory.createLineBorder(Color.GRAY)); // add main panel to XSheet mainPanel = new JPanel(); mainPanel.setLayout(new BorderLayout()); @@ -129,17 +120,32 @@ mbeanInfo = new XMBeanInfo(); } - public boolean isMBeanNode(DefaultMutableTreeNode node) { - XNodeInfo uo = (XNodeInfo) node.getUserObject(); - return uo.getType().equals(Type.MBEAN); + private boolean isSelectedNode(DefaultMutableTreeNode n, DefaultMutableTreeNode cn) { + return (cn == n); + } + + // Call on EDT + private void showErrorDialog(Object message, String title) { + new ThreadDialog(this, message, title, JOptionPane.ERROR_MESSAGE).run(); } - public void displayNode(DefaultMutableTreeNode node) { + public boolean isMBeanNode(DefaultMutableTreeNode node) { + Object userObject = node.getUserObject(); + if (userObject instanceof XNodeInfo) { + XNodeInfo uo = (XNodeInfo) userObject; + return uo.getType().equals(Type.MBEAN); + } + return false; + } + + // Call on EDT + public synchronized void displayNode(DefaultMutableTreeNode node) { clear(); + displayEmptyNode(); if (node == null) { - displayEmptyNode(); return; } + currentNode = node; Object userObject = node.getUserObject(); if (userObject instanceof XNodeInfo) { XNodeInfo uo = (XNodeInfo) userObject; @@ -173,27 +179,28 @@ } } + // Call on EDT private void displayMBeanNode(final DefaultMutableTreeNode node) { final XNodeInfo uo = (XNodeInfo) node.getUserObject(); if (!uo.getType().equals(Type.MBEAN)) { return; } - mbeansTab.workerAdd(new Runnable() { - public void run() { + mbean = (XMBean) uo.getData(); + SwingWorker sw = new SwingWorker() { + @Override + public MBeanInfo doInBackground() throws InstanceNotFoundException, + IntrospectionException, ReflectionException, IOException { + return mbean.getMBeanInfo(); + } + @Override + protected void done() { try { - XSheet.this.node = node; - XSheet.this.mbean = (XMBean) uo.getData(); - mbeanInfo.addMBeanInfo(mbean, mbean.getMBeanInfo()); - } catch (Throwable ex) { - EventQueue.invokeLater(new ThreadDialog( - XSheet.this, - ex.getMessage(), - Resources.getText("Problem displaying MBean"), - JOptionPane.ERROR_MESSAGE)); - return; - } - EventQueue.invokeLater(new Runnable() { - public void run() { + MBeanInfo mbi = get(); + if (mbi != null) { + if (!isSelectedNode(node, currentNode)) { + return; + } + mbeanInfo.addMBeanInfo(mbean, mbi); invalidate(); mainPanel.removeAll(); mainPanel.add(mbeanInfo, BorderLayout.CENTER); @@ -202,9 +209,19 @@ validate(); repaint(); } - }); + } catch (Exception e) { + Throwable t = Utils.getActualException(e); + if (JConsole.isDebug()) { + System.err.println("Couldn't get MBeanInfo for MBean [" + + mbean.getObjectName() + "]"); + t.printStackTrace(); + } + showErrorDialog(t.toString(), + Resources.getText("Problem displaying MBean")); + } } - }); + }; + sw.execute(); } // Call on EDT @@ -213,90 +230,90 @@ final XMBeanInfo mbi = mbeanInfo; switch (uo.getType()) { case ATTRIBUTE: - mbeansTab.workerAdd(new Runnable() { - public void run() { - Object attrData = uo.getData(); - XSheet.this.mbean = (XMBean) ((Object[]) attrData)[0]; - final MBeanAttributeInfo mbai = - (MBeanAttributeInfo) ((Object[]) attrData)[1]; - final XMBeanAttributes mba = mbeanAttributes; - try { - mba.loadAttributes(mbean, new MBeanInfo( - null, null, new MBeanAttributeInfo[] {mbai}, - null, null, null)); - } catch (Exception e) { - EventQueue.invokeLater(new ThreadDialog( - XSheet.this, - e.getMessage(), - Resources.getText("Problem displaying MBean"), - JOptionPane.ERROR_MESSAGE)); - return; - } - EventQueue.invokeLater(new Runnable() { - public void run() { - invalidate(); - mainPanel.removeAll(); - JPanel attributePanel = - new JPanel(new BorderLayout()); - JPanel attributeBorderPanel = - new JPanel(new BorderLayout()); - attributeBorderPanel.setBorder( - BorderFactory.createTitledBorder( - Resources.getText("Attribute value"))); - JPanel attributeValuePanel = - new JPanel(new BorderLayout()); - attributeValuePanel.setBorder( - LineBorder.createGrayLineBorder()); - attributeValuePanel.add(mba.getTableHeader(), - BorderLayout.PAGE_START); - attributeValuePanel.add(mba, - BorderLayout.CENTER); - attributeBorderPanel.add(attributeValuePanel, - BorderLayout.CENTER); - JPanel refreshButtonPanel = new JPanel(); - refreshButtonPanel.add(refreshButton); - attributeBorderPanel.add(refreshButtonPanel, - BorderLayout.SOUTH); - refreshButton.setEnabled(true); - attributePanel.add(attributeBorderPanel, - BorderLayout.NORTH); - mbi.addMBeanAttributeInfo(mbai); - attributePanel.add(mbi, BorderLayout.CENTER); - mainPanel.add(attributePanel, - BorderLayout.CENTER); - southPanel.setVisible(false); - southPanel.removeAll(); - validate(); - repaint(); + SwingWorker sw = + new SwingWorker() { + @Override + public MBeanAttributeInfo doInBackground() { + Object attrData = uo.getData(); + mbean = (XMBean) ((Object[]) attrData)[0]; + MBeanAttributeInfo mbai = + (MBeanAttributeInfo) ((Object[]) attrData)[1]; + mbeanAttributes.loadAttributes(mbean, new MBeanInfo( + null, null, new MBeanAttributeInfo[]{mbai}, + null, null, null)); + return mbai; } - }); - } - }); + @Override + protected void done() { + try { + MBeanAttributeInfo mbai = get(); + if (!isSelectedNode(node, currentNode)) { + return; + } + invalidate(); + mainPanel.removeAll(); + JPanel attributePanel = + new JPanel(new BorderLayout()); + JPanel attributeBorderPanel = + new JPanel(new BorderLayout()); + attributeBorderPanel.setBorder( + BorderFactory.createTitledBorder( + Resources.getText("Attribute value"))); + JPanel attributeValuePanel = + new JPanel(new BorderLayout()); + attributeValuePanel.setBorder( + LineBorder.createGrayLineBorder()); + attributeValuePanel.add(mbeanAttributes.getTableHeader(), + BorderLayout.PAGE_START); + attributeValuePanel.add(mbeanAttributes, + BorderLayout.CENTER); + attributeBorderPanel.add(attributeValuePanel, + BorderLayout.CENTER); + JPanel refreshButtonPanel = new JPanel(); + refreshButtonPanel.add(refreshButton); + attributeBorderPanel.add(refreshButtonPanel, + BorderLayout.SOUTH); + refreshButton.setEnabled(true); + attributePanel.add(attributeBorderPanel, + BorderLayout.NORTH); + mbi.addMBeanAttributeInfo(mbai); + attributePanel.add(mbi, BorderLayout.CENTER); + mainPanel.add(attributePanel, + BorderLayout.CENTER); + southPanel.setVisible(false); + southPanel.removeAll(); + validate(); + repaint(); + } catch (Exception e) { + Throwable t = Utils.getActualException(e); + if (JConsole.isDebug()) { + System.err.println("Problem displaying MBean " + + "attribute for MBean [" + + mbean.getObjectName() + "]"); + t.printStackTrace(); + } + showErrorDialog(t.toString(), + Resources.getText("Problem displaying MBean")); + } + } + }; + sw.execute(); break; case OPERATION: Object operData = uo.getData(); - XSheet.this.mbean = (XMBean) ((Object[]) operData)[0]; + mbean = (XMBean) ((Object[]) operData)[0]; MBeanOperationInfo mboi = (MBeanOperationInfo) ((Object[]) operData)[1]; - XMBeanOperations mbo = mbeanOperations; - try { - mbo.loadOperations(mbean, new MBeanInfo(null, null, null, - null, new MBeanOperationInfo[] {mboi}, null)); - } catch (Exception e) { - EventQueue.invokeLater(new ThreadDialog( - XSheet.this, - e.getMessage(), - Resources.getText("Problem displaying MBean"), - JOptionPane.ERROR_MESSAGE)); - return; - } + mbeanOperations.loadOperations(mbean, + new MBeanInfo(null, null, null, null, + new MBeanOperationInfo[]{mboi}, null)); invalidate(); mainPanel.removeAll(); JPanel operationPanel = new JPanel(new BorderLayout()); JPanel operationBorderPanel = new JPanel(new BorderLayout()); operationBorderPanel.setBorder(BorderFactory.createTitledBorder( Resources.getText("Operation invocation"))); - operationBorderPanel.add(new JScrollPane(mbo)); + operationBorderPanel.add(new JScrollPane(mbeanOperations)); operationPanel.add(operationBorderPanel, BorderLayout.NORTH); mbi.addMBeanOperationInfo(mboi); operationPanel.add(mbi, BorderLayout.CENTER); @@ -320,134 +337,134 @@ } } + // Call on EDT private void displayMBeanAttributesNode(final DefaultMutableTreeNode node) { final XNodeInfo uo = (XNodeInfo) node.getUserObject(); if (!uo.getType().equals(Type.ATTRIBUTES)) { return; } - final XMBeanAttributes mba = mbeanAttributes; - mbeansTab.workerAdd(new Runnable() { - public void run() { + mbean = (XMBean) uo.getData(); + SwingWorker sw = new SwingWorker() { + @Override + public Void doInBackground() throws InstanceNotFoundException, + IntrospectionException, ReflectionException, IOException { + mbeanAttributes.loadAttributes(mbean, mbean.getMBeanInfo()); + return null; + } + @Override + protected void done() { try { - XSheet.this.node = node; - XSheet.this.mbean = (XMBean) uo.getData(); - mba.loadAttributes(mbean, mbean.getMBeanInfo()); - } catch (Throwable ex) { - EventQueue.invokeLater(new ThreadDialog( - XSheet.this, - ex.getMessage(), - Resources.getText("Problem displaying MBean"), - JOptionPane.ERROR_MESSAGE)); - return; + get(); + if (!isSelectedNode(node, currentNode)) { + return; + } + invalidate(); + mainPanel.removeAll(); + JPanel borderPanel = new JPanel(new BorderLayout()); + borderPanel.setBorder(BorderFactory.createTitledBorder( + Resources.getText("Attribute values"))); + borderPanel.add(new JScrollPane(mbeanAttributes)); + mainPanel.add(borderPanel, BorderLayout.CENTER); + // add the refresh button to the south panel + southPanel.removeAll(); + southPanel.add(refreshButton, BorderLayout.SOUTH); + southPanel.setVisible(true); + refreshButton.setEnabled(true); + validate(); + repaint(); + } catch (Exception e) { + Throwable t = Utils.getActualException(e); + if (JConsole.isDebug()) { + System.err.println("Problem displaying MBean " + + "attributes for MBean [" + + mbean.getObjectName() + "]"); + t.printStackTrace(); + } + showErrorDialog(t.toString(), + Resources.getText("Problem displaying MBean")); } - EventQueue.invokeLater(new Runnable() { - public void run() { - invalidate(); - mainPanel.removeAll(); - JPanel borderPanel = new JPanel(new BorderLayout()); - borderPanel.setBorder(BorderFactory.createTitledBorder( - Resources.getText("Attribute values"))); - borderPanel.add(new JScrollPane(mba)); - mainPanel.add(borderPanel, BorderLayout.CENTER); - // add the refresh button to the south panel - southPanel.removeAll(); - southPanel.add(refreshButton, BorderLayout.SOUTH); - southPanel.setVisible(true); - refreshButton.setEnabled(true); - validate(); - repaint(); - } - }); } - }); + }; + sw.execute(); } + // Call on EDT private void displayMBeanOperationsNode(final DefaultMutableTreeNode node) { final XNodeInfo uo = (XNodeInfo) node.getUserObject(); if (!uo.getType().equals(Type.OPERATIONS)) { return; } - final XMBeanOperations mbo = mbeanOperations; - mbeansTab.workerAdd(new Runnable() { - public void run() { + mbean = (XMBean) uo.getData(); + SwingWorker sw = new SwingWorker() { + @Override + public MBeanInfo doInBackground() throws InstanceNotFoundException, + IntrospectionException, ReflectionException, IOException { + return mbean.getMBeanInfo(); + } + @Override + protected void done() { try { - XSheet.this.node = node; - XSheet.this.mbean = (XMBean) uo.getData(); - mbo.loadOperations(mbean, mbean.getMBeanInfo()); - } catch (Throwable ex) { - EventQueue.invokeLater(new ThreadDialog( - XSheet.this, - ex.getMessage(), - Resources.getText("Problem displaying MBean"), - JOptionPane.ERROR_MESSAGE)); - return; - } - EventQueue.invokeLater(new Runnable() { - public void run() { + MBeanInfo mbi = get(); + if (mbi != null) { + if (!isSelectedNode(node, currentNode)) { + return; + } + mbeanOperations.loadOperations(mbean, mbi); invalidate(); mainPanel.removeAll(); JPanel borderPanel = new JPanel(new BorderLayout()); borderPanel.setBorder(BorderFactory.createTitledBorder( Resources.getText("Operation invocation"))); - borderPanel.add(new JScrollPane(mbo)); + borderPanel.add(new JScrollPane(mbeanOperations)); mainPanel.add(borderPanel, BorderLayout.CENTER); southPanel.setVisible(false); southPanel.removeAll(); validate(); repaint(); } - }); + } catch (Exception e) { + Throwable t = Utils.getActualException(e); + if (JConsole.isDebug()) { + System.err.println("Problem displaying MBean " + + "operations for MBean [" + + mbean.getObjectName() + "]"); + t.printStackTrace(); + } + showErrorDialog(t.toString(), + Resources.getText("Problem displaying MBean")); + } } - }); + }; + sw.execute(); } - private void displayMBeanNotificationsNode( - final DefaultMutableTreeNode node) { + // Call on EDT + private void displayMBeanNotificationsNode(DefaultMutableTreeNode node) { final XNodeInfo uo = (XNodeInfo) node.getUserObject(); if (!uo.getType().equals(Type.NOTIFICATIONS)) { return; } - final XMBeanNotifications mbn = mbeanNotifications; - mbeansTab.workerAdd(new Runnable() { - public void run() { - try { - XSheet.this.node = node; - XSheet.this.mbean = (XMBean) uo.getData(); - mbn.loadNotifications(mbean); - updateNotifications(); - } catch (Throwable ex) { - EventQueue.invokeLater(new ThreadDialog( - XSheet.this, - ex.getMessage(), - Resources.getText("Problem displaying MBean"), - JOptionPane.ERROR_MESSAGE)); - return; - } - EventQueue.invokeLater(new Runnable() { - public void run() { - invalidate(); - mainPanel.removeAll(); - JPanel borderPanel = new JPanel(new BorderLayout()); - borderPanel.setBorder(BorderFactory.createTitledBorder( - Resources.getText("Notification buffer"))); - borderPanel.add(new JScrollPane(mbn)); - mainPanel.add(borderPanel, BorderLayout.CENTER); - // add the subscribe/unsubscribe/clear buttons to - // the south panel - southPanel.removeAll(); - southPanel.add(subscribeButton, BorderLayout.WEST); - southPanel.add(unsubscribeButton, BorderLayout.CENTER); - southPanel.add(clearButton, BorderLayout.EAST); - southPanel.setVisible(true); - subscribeButton.setEnabled(true); - unsubscribeButton.setEnabled(true); - clearButton.setEnabled(true); - validate(); - repaint(); - } - }); - } - }); + mbean = (XMBean) uo.getData(); + mbeanNotifications.loadNotifications(mbean); + updateNotifications(); + invalidate(); + mainPanel.removeAll(); + JPanel borderPanel = new JPanel(new BorderLayout()); + borderPanel.setBorder(BorderFactory.createTitledBorder( + Resources.getText("Notification buffer"))); + borderPanel.add(new JScrollPane(mbeanNotifications)); + mainPanel.add(borderPanel, BorderLayout.CENTER); + // add the subscribe/unsubscribe/clear buttons to the south panel + southPanel.removeAll(); + southPanel.add(subscribeButton, BorderLayout.WEST); + southPanel.add(unsubscribeButton, BorderLayout.CENTER); + southPanel.add(clearButton, BorderLayout.EAST); + southPanel.setVisible(true); + subscribeButton.setEnabled(true); + unsubscribeButton.setEnabled(true); + clearButton.setEnabled(true); + validate(); + repaint(); } // Call on EDT @@ -462,21 +479,60 @@ /** * Subscribe button action. */ - private void registerListener() throws InstanceNotFoundException, - IOException { - mbeanNotifications.registerListener(node); - updateNotifications(); - validate(); + private void registerListener() { + new SwingWorker() { + @Override + public Void doInBackground() + throws InstanceNotFoundException, IOException { + mbeanNotifications.registerListener(currentNode); + return null; + } + @Override + protected void done() { + try { + get(); + updateNotifications(); + validate(); + } catch (Exception e) { + Throwable t = Utils.getActualException(e); + if (JConsole.isDebug()) { + System.err.println("Problem adding listener"); + t.printStackTrace(); + } + showErrorDialog(t.getMessage(), + Resources.getText("Problem adding listener")); + } + } + }.execute(); } /** * Unsubscribe button action. */ private void unregisterListener() { - if (mbeanNotifications.unregisterListener(node)) { - clearNotifications(); - validate(); - } + new SwingWorker() { + @Override + public Boolean doInBackground() { + return mbeanNotifications.unregisterListener(currentNode); + } + @Override + protected void done() { + try { + if (get()) { + updateNotifications(); + validate(); + } + } catch (Exception e) { + Throwable t = Utils.getActualException(e); + if (JConsole.isDebug()) { + System.err.println("Problem removing listener"); + t.printStackTrace(); + } + showErrorDialog(t.getMessage(), + Resources.getText("Problem removing listener")); + } + } + }.execute(); } /** @@ -486,15 +542,11 @@ mbeanAttributes.refreshAttributes(); } + // Call on EDT private void updateNotifications() { - if (mbean.isBroadcaster()) { - if (mbeanNotifications.isListenerRegistered(mbean)) { - long received = - mbeanNotifications.getReceivedNotifications(mbean); - updateReceivedNotifications(node, received, false); - } else { - clearNotifications(); - } + if (mbeanNotifications.isListenerRegistered(mbean)) { + long received = mbeanNotifications.getReceivedNotifications(mbean); + updateReceivedNotifications(currentNode, received, false); } else { clearNotifications(); } @@ -503,11 +555,11 @@ /** * Update notification node label in MBean tree: "Notifications[received]". */ + // Call on EDT private void updateReceivedNotifications( DefaultMutableTreeNode emitter, long received, boolean bold) { String text = Resources.getText("Notifications") + "[" + received + "]"; - DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) - mbeansTab.getTree().getLastSelectedPathComponent(); + DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) mbeansTab.getTree().getLastSelectedPathComponent(); if (bold && emitter != selectedNode) { text = "" + text + ""; } @@ -517,41 +569,40 @@ /** * Update notification node label in MBean tree: "Notifications". */ + // Call on EDT private void clearNotifications() { - updateNotificationsNodeLabel(node, + updateNotificationsNodeLabel(currentNode, Resources.getText("Notifications")); } /** * Update notification node label in MBean tree: "Notifications[0]". */ + // Call on EDT private void clearNotifications0() { - updateNotificationsNodeLabel(node, + updateNotificationsNodeLabel(currentNode, Resources.getText("Notifications") + "[0]"); } /** * Update the label of the supplied MBean tree node. */ + // Call on EDT private void updateNotificationsNodeLabel( - final DefaultMutableTreeNode node, final String label) { - EventQueue.invokeLater(new Runnable() { - public void run() { - synchronized (mbeansTab.getTree()) { - invalidate(); - XNodeInfo oldUserObject = (XNodeInfo) node.getUserObject(); - XNodeInfo newUserObject = new XNodeInfo( - oldUserObject.getType(), oldUserObject.getData(), - label, oldUserObject.getToolTipText()); - node.setUserObject(newUserObject); - DefaultTreeModel model = - (DefaultTreeModel) mbeansTab.getTree().getModel(); - model.nodeChanged(node); - validate(); - repaint(); - } - } - }); + DefaultMutableTreeNode node, String label) { + synchronized (mbeansTab.getTree()) { + invalidate(); + XNodeInfo oldUserObject = (XNodeInfo) node.getUserObject(); + XNodeInfo newUserObject = new XNodeInfo( + oldUserObject.getType(), oldUserObject.getData(), + label, oldUserObject.getToolTipText()); + node.setUserObject(newUserObject); + DefaultTreeModel model = + (DefaultTreeModel) mbeansTab.getTree().getModel(); + model.nodeChanged(node); + validate(); + repaint(); + } } /** @@ -577,6 +628,7 @@ } } + // Call on EDT private void clear() { mbeanAttributes.stopCellEditing(); mbeanAttributes.emptyTable(); @@ -586,13 +638,14 @@ mbeanNotifications.emptyTable(); mbeanNotifications.disableNotifications(); mbean = null; - node = null; + currentNode = null; } /** * Notification listener: handles asynchronous reception * of MBean operation results and MBean notifications. */ + // Call on EDT public void handleNotification(Notification e, Object handback) { // Operation result if (e.getType().equals(XOperations.OPERATION_INVOCATION_EVENT)) { @@ -628,13 +681,12 @@ message = comp; } } - EventQueue.invokeLater(new ThreadDialog( + new ThreadDialog( (Component) e.getSource(), message, Resources.getText("Operation return value"), - JOptionPane.INFORMATION_MESSAGE)); - } - // Got notification + JOptionPane.INFORMATION_MESSAGE).run(); + } // Got notification else if (e.getType().equals( XMBeanNotifications.NOTIFICATION_RECEIVED_EVENT)) { DefaultMutableTreeNode emitter = (DefaultMutableTreeNode) handback; @@ -646,16 +698,19 @@ /** * Action listener: handles actions in panel buttons */ + // Call on EDT public void actionPerformed(ActionEvent e) { if (e.getSource() instanceof JButton) { JButton button = (JButton) e.getSource(); // Refresh button if (button == refreshButton) { - mbeansTab.workerAdd(new Runnable() { - public void run() { + new SwingWorker() { + @Override + public Void doInBackground() { refreshAttributes(); + return null; } - }); + }.execute(); return; } // Clear button @@ -665,38 +720,12 @@ } // Subscribe button if (button == subscribeButton) { - mbeansTab.workerAdd(new Runnable() { - public void run() { - try { - registerListener(); - } catch (Throwable ex) { - ex = Utils.getActualException(ex); - EventQueue.invokeLater(new ThreadDialog( - XSheet.this, - ex.getMessage(), - Resources.getText("Problem adding listener"), - JOptionPane.ERROR_MESSAGE)); - } - } - }); + registerListener(); return; } // Unsubscribe button if (button == unsubscribeButton) { - mbeansTab.workerAdd(new Runnable() { - public void run() { - try { - unregisterListener(); - } catch (Throwable ex) { - ex = Utils.getActualException(ex); - EventQueue.invokeLater(new ThreadDialog( - XSheet.this, - ex.getMessage(), - Resources.getText("Problem removing listener"), - JOptionPane.ERROR_MESSAGE)); - } - } - }); + unregisterListener(); return; } } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/tools/jconsole/inspector/XTable.java --- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XTable.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XTable.java Tue Mar 11 23:37:02 2008 -0700 @@ -22,6 +22,7 @@ * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ + package sun.tools.jconsole.inspector; import javax.swing.*; diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/tools/jconsole/inspector/XTextField.java --- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XTextField.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XTextField.java Tue Mar 11 23:37:02 2008 -0700 @@ -22,6 +22,7 @@ * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ + package sun.tools.jconsole.inspector; import java.awt.*; diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/tools/jconsole/inspector/XTextFieldEditor.java --- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XTextFieldEditor.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XTextFieldEditor.java Tue Mar 11 23:37:02 2008 -0700 @@ -22,6 +22,7 @@ * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ + package sun.tools.jconsole.inspector; import java.awt.Component; diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/tools/jconsole/inspector/XTree.java --- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XTree.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XTree.java Tue Mar 11 23:37:02 2008 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2004-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ package sun.tools.jconsole.inspector; -import java.awt.EventQueue; +import java.io.IOException; import java.util.*; import javax.management.*; import javax.swing.*; @@ -34,13 +34,14 @@ import sun.tools.jconsole.MBeansTab; import sun.tools.jconsole.Resources; import sun.tools.jconsole.inspector.XNodeInfo; -import sun.tools.jconsole.inspector.XNodeInfo.Type; +import static sun.tools.jconsole.inspector.XNodeInfo.Type; @SuppressWarnings("serial") public class XTree extends JTree { private static final List orderedKeyPropertyList = new ArrayList(); + static { String keyPropertyList = System.getProperty("com.sun.tools.jconsole.mbeans.keyPropertyList"); @@ -54,9 +55,7 @@ } } } - private MBeansTab mbeansTab; - private Map nodes = new HashMap(); @@ -65,7 +64,7 @@ } public XTree(TreeNode root, MBeansTab mbeansTab) { - super(root); + super(root, true); this.mbeansTab = mbeansTab; setRootVisible(false); setShowsRootHandles(true); @@ -90,15 +89,8 @@ DefaultMutableTreeNode parent, DefaultMutableTreeNode child, int index) { - // Tree does not show up when there is only the root node - // DefaultTreeModel model = (DefaultTreeModel) getModel(); - DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot(); - boolean rootLeaf = root.isLeaf(); model.insertNodeInto(child, parent, index); - if (rootLeaf) { - model.nodeStructureChanged(root); - } } /** @@ -114,32 +106,29 @@ int childCount = parent.getChildCount(); if (childCount == 0) { addChildNode(parent, child, 0); - } else if (child instanceof ComparableDefaultMutableTreeNode) { + return; + } + if (child instanceof ComparableDefaultMutableTreeNode) { ComparableDefaultMutableTreeNode comparableChild = - (ComparableDefaultMutableTreeNode)child; - int i = 0; - for (; i < childCount; i++) { + (ComparableDefaultMutableTreeNode) child; + for (int i = childCount - 1; i >= 0; i--) { DefaultMutableTreeNode brother = (DefaultMutableTreeNode) parent.getChildAt(i); - //child < brother - if (comparableChild.compareTo(brother) < 0) { - addChildNode(parent, child, i); - break; - } - //child = brother - else if (comparableChild.compareTo(brother) == 0) { - addChildNode(parent, child, i); - break; + // expr1: child node must be inserted after metadata nodes + // - OR - + // expr2: "child >= brother" + if ((i <= 2 && isMetadataNode(brother)) || + comparableChild.compareTo(brother) >= 0) { + addChildNode(parent, child, i + 1); + return; } } - //child < all brothers - if (i == childCount) { - addChildNode(parent, child, childCount); - } - } else { - //not comparable, add at the end - addChildNode(parent, child, childCount); + // "child < all brothers", add at the beginning + addChildNode(parent, child, 0); + return; } + // "child not comparable", add at the end + addChildNode(parent, child, childCount); } /** @@ -147,6 +136,7 @@ * but does not affect actual MBeanServer contents. */ // Call on EDT + @Override public synchronized void removeAll() { DefaultTreeModel model = (DefaultTreeModel) getModel(); DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot(); @@ -155,51 +145,56 @@ nodes.clear(); } - public void delMBeanFromView(final ObjectName mbean) { - EventQueue.invokeLater(new Runnable() { - public void run() { - // We assume here that MBeans are removed one by one (on MBean - // unregistered notification). Deletes the tree node associated - // with the given MBean and recursively all the node parents - // which are leaves and non XMBean. - // - synchronized (XTree.this) { - DefaultMutableTreeNode node = null; - Dn dn = buildDn(mbean); - if (dn.size() > 0) { - DefaultTreeModel model = (DefaultTreeModel) getModel(); - Token token = dn.getToken(0); - String hashKey = dn.getHashKey(token); - node = nodes.get(hashKey); - if ((node != null) && (!node.isRoot())) { - if (hasMBeanChildren(node)) { - removeNonMBeanChildren(node); - String label = token.getValue().toString(); - XNodeInfo userObject = new XNodeInfo( - Type.NONMBEAN, label, - label, token.toString()); - changeNodeValue(node, userObject); - } else { - DefaultMutableTreeNode parent = - (DefaultMutableTreeNode) node.getParent(); - model.removeNodeFromParent(node); - nodes.remove(hashKey); - delParentFromView(dn, 1, parent); - } - } - } + // Call on EDT + public synchronized void removeMBeanFromView(ObjectName mbean) { + // We assume here that MBeans are removed one by one (on MBean + // unregistered notification). Deletes the tree node associated + // with the given MBean and recursively all the node parents + // which are leaves and non XMBean. + // + DefaultMutableTreeNode node = null; + Dn dn = new Dn(mbean); + if (dn.getTokenCount() > 0) { + DefaultTreeModel model = (DefaultTreeModel) getModel(); + Token token = dn.getToken(0); + String hashKey = dn.getHashKey(token); + node = nodes.get(hashKey); + if ((node != null) && (!node.isRoot())) { + if (hasNonMetadataNodes(node)) { + removeMetadataNodes(node); + String label = token.getValue(); + XNodeInfo userObject = new XNodeInfo( + Type.NONMBEAN, label, + label, token.getTokenValue()); + changeNodeValue(node, userObject); + } else { + DefaultMutableTreeNode parent = + (DefaultMutableTreeNode) node.getParent(); + model.removeNodeFromParent(node); + nodes.remove(hashKey); + removeParentFromView(dn, 1, parent); } } - }); + } } /** - * Returns true if any of the children nodes is an MBean. + * Returns true if any of the children nodes is a non MBean metadata node. */ - private boolean hasMBeanChildren(DefaultMutableTreeNode node) { - for (Enumeration e = node.children(); e.hasMoreElements(); ) { + private boolean hasNonMetadataNodes(DefaultMutableTreeNode node) { + for (Enumeration e = node.children(); e.hasMoreElements();) { DefaultMutableTreeNode n = (DefaultMutableTreeNode) e.nextElement(); - if (((XNodeInfo) n.getUserObject()).getType().equals(Type.MBEAN)) { + Object uo = n.getUserObject(); + if (uo instanceof XNodeInfo) { + switch (((XNodeInfo) uo).getType()) { + case ATTRIBUTES: + case NOTIFICATIONS: + case OPERATIONS: + break; + default: + return true; + } + } else { return true; } } @@ -207,16 +202,68 @@ } /** - * Remove all the children nodes which are not MBean. + * Returns true if any of the children nodes is an MBean metadata node. */ - private void removeNonMBeanChildren(DefaultMutableTreeNode node) { + public boolean hasMetadataNodes(DefaultMutableTreeNode node) { + for (Enumeration e = node.children(); e.hasMoreElements();) { + DefaultMutableTreeNode n = (DefaultMutableTreeNode) e.nextElement(); + Object uo = n.getUserObject(); + if (uo instanceof XNodeInfo) { + switch (((XNodeInfo) uo).getType()) { + case ATTRIBUTES: + case NOTIFICATIONS: + case OPERATIONS: + return true; + default: + break; + } + } else { + return false; + } + } + return false; + } + + /** + * Returns true if the given node is an MBean metadata node. + */ + public boolean isMetadataNode(DefaultMutableTreeNode node) { + Object uo = node.getUserObject(); + if (uo instanceof XNodeInfo) { + switch (((XNodeInfo) uo).getType()) { + case ATTRIBUTES: + case NOTIFICATIONS: + case OPERATIONS: + return true; + default: + return false; + } + } else { + return false; + } + } + + /** + * Remove the metadata nodes associated with a given MBean node. + */ + // Call on EDT + private void removeMetadataNodes(DefaultMutableTreeNode node) { Set metadataNodes = new HashSet(); DefaultTreeModel model = (DefaultTreeModel) getModel(); - for (Enumeration e = node.children(); e.hasMoreElements(); ) { + for (Enumeration e = node.children(); e.hasMoreElements();) { DefaultMutableTreeNode n = (DefaultMutableTreeNode) e.nextElement(); - if (!((XNodeInfo) n.getUserObject()).getType().equals(Type.MBEAN)) { - metadataNodes.add(n); + Object uo = n.getUserObject(); + if (uo instanceof XNodeInfo) { + switch (((XNodeInfo) uo).getType()) { + case ATTRIBUTES: + case NOTIFICATIONS: + case OPERATIONS: + metadataNodes.add(n); + break; + default: + break; + } } } for (DefaultMutableTreeNode n : metadataNodes) { @@ -228,7 +275,8 @@ * Removes only the parent nodes which are non MBean and leaf. * This method assumes the child nodes have been removed before. */ - private DefaultMutableTreeNode delParentFromView( + // Call on EDT + private DefaultMutableTreeNode removeParentFromView( Dn dn, int index, DefaultMutableTreeNode node) { if ((!node.isRoot()) && node.isLeaf() && (!(((XNodeInfo) node.getUserObject()).getType().equals(Type.MBEAN)))) { @@ -237,115 +285,100 @@ removeChildNode(node); String hashKey = dn.getHashKey(dn.getToken(index)); nodes.remove(hashKey); - delParentFromView(dn, index + 1, parent); + removeParentFromView(dn, index + 1, parent); } return node; } - public synchronized void addMBeanToView(final ObjectName mbean) { - final XMBean xmbean; - try { - xmbean = new XMBean(mbean, mbeansTab); - if (xmbean == null) { - return; - } - } catch (Exception e) { - // Got exception while trying to retrieve the - // given MBean from the underlying MBeanServer + // Call on EDT + public synchronized void addMBeansToView(Set mbeans) { + Set dns = new TreeSet(); + for (ObjectName mbean : mbeans) { + Dn dn = new Dn(mbean); + dns.add(dn); + } + for (Dn dn : dns) { + ObjectName mbean = dn.getObjectName(); + XMBean xmbean = new XMBean(mbean, mbeansTab); + addMBeanToView(mbean, xmbean, dn); + } + } + + // Call on EDT + public synchronized void addMBeanToView(ObjectName mbean) { + // Build XMBean for the given MBean + // + XMBean xmbean = new XMBean(mbean, mbeansTab); + // Build Dn for the given MBean + // + Dn dn = new Dn(mbean); + // Add the new nodes to the MBean tree from leaf to root + // + addMBeanToView(mbean, xmbean, dn); + } + + // Call on EDT + private synchronized void addMBeanToView( + ObjectName mbean, XMBean xmbean, Dn dn) { + + DefaultMutableTreeNode childNode = null; + DefaultMutableTreeNode parentNode = null; + + // Add the node or replace its user object if already added + // + Token token = dn.getToken(0); + String hashKey = dn.getHashKey(token); + if (nodes.containsKey(hashKey)) { + // Found existing node previously created when adding another node // - if (JConsole.isDebug()) { - e.printStackTrace(); - } + childNode = nodes.get(hashKey); + // Replace user object to reflect that this node is an MBean + // + Object data = createNodeValue(xmbean, token); + String label = data.toString(); + XNodeInfo userObject = + new XNodeInfo(Type.MBEAN, data, label, mbean.toString()); + changeNodeValue(childNode, userObject); return; } - EventQueue.invokeLater(new Runnable() { - public void run() { - synchronized (XTree.this) { - // Add the new nodes to the MBean tree from leaf to root - Dn dn = buildDn(mbean); - if (dn.size() == 0) return; - Token token = dn.getToken(0); - DefaultMutableTreeNode node = null; - boolean nodeCreated = true; - - // - // Add the node or replace its user object if already added - // - - String hashKey = dn.getHashKey(token); - if (nodes.containsKey(hashKey)) { - //already in the tree, means it has been created previously - //when adding another node - node = nodes.get(hashKey); - //sets the user object - final Object data = createNodeValue(xmbean, token); - final String label = data.toString(); - final XNodeInfo userObject = - new XNodeInfo(Type.MBEAN, data, label, mbean.toString()); - changeNodeValue(node, userObject); - nodeCreated = false; - } else { - //create a new node - node = createDnNode(dn, token, xmbean); - if (node != null) { - nodes.put(hashKey, node); - nodeCreated = true; - } else { - return; - } - } - - // - // Add (virtual) nodes without user object if necessary - // + // Create new leaf node + // + childNode = createDnNode(dn, token, xmbean); + nodes.put(hashKey, childNode); - for (int i = 1; i < dn.size(); i++) { - DefaultMutableTreeNode currentNode = null; - token = dn.getToken(i); - hashKey = dn.getHashKey(token); - if (nodes.containsKey(hashKey)) { - //node already present - if (nodeCreated) { - //previous node created, link to do - currentNode = nodes.get(hashKey); - addChildNode(currentNode, node); - return; - } else { - //both nodes already present - return; - } - } else { - //creates the node that can be a virtual one - if (token.getKeyDn().equals("domain")) { - //better match on keyDn that on Dn - currentNode = createDomainNode(dn, token); - if (currentNode != null) { - final DefaultMutableTreeNode root = - (DefaultMutableTreeNode) getModel().getRoot(); - addChildNode(root, currentNode); - } - } else { - currentNode = createSubDnNode(dn, token); - if (currentNode == null) { - //skip - continue; - } - } - nodes.put(hashKey, currentNode); - addChildNode(currentNode, node); - nodeCreated = true; - } - node = currentNode; - } + // Add intermediate non MBean nodes + // + for (int i = 1; i < dn.getTokenCount(); i++) { + token = dn.getToken(i); + hashKey = dn.getHashKey(token); + if (nodes.containsKey(hashKey)) { + // Intermediate node already present, add new node as child + // + parentNode = nodes.get(hashKey); + addChildNode(parentNode, childNode); + return; + } else { + // Create new intermediate node + // + if ("domain".equals(token.getTokenType())) { + parentNode = createDomainNode(dn, token); + DefaultMutableTreeNode root = + (DefaultMutableTreeNode) getModel().getRoot(); + addChildNode(root, parentNode); + } else { + parentNode = createSubDnNode(dn, token); } + nodes.put(hashKey, parentNode); + addChildNode(parentNode, childNode); } - }); + childNode = parentNode; + } } // Call on EDT private synchronized void changeNodeValue( - final DefaultMutableTreeNode node, XNodeInfo nodeValue) { + DefaultMutableTreeNode node, XNodeInfo nodeValue) { if (node instanceof ComparableDefaultMutableTreeNode) { // should it stay at the same place? DefaultMutableTreeNode clone = @@ -373,9 +406,12 @@ } // Load the MBean metadata if type is MBEAN if (nodeValue.getType().equals(Type.MBEAN)) { - XMBeanInfo.loadInfo(node); - DefaultTreeModel model = (DefaultTreeModel) getModel(); - model.nodeStructureChanged(node); + removeMetadataNodes(node); + TreeNode[] treeNodes = node.getPath(); + TreePath path = new TreePath(treeNodes); + if (isExpanded(path)) { + addMetadataNodes(node); + } } // Clear the current selection and set it // again so valueChanged() gets called @@ -386,7 +422,9 @@ } } - //creates the domain node, called on a domain token + /** + * Creates the domain node. + */ private DefaultMutableTreeNode createDomainNode(Dn dn, Token token) { DefaultMutableTreeNode node = new ComparableDefaultMutableTreeNode(); String label = dn.getDomain(); @@ -396,7 +434,9 @@ return node; } - //creates the node corresponding to the whole Dn + /** + * Creates the node corresponding to the whole Dn, i.e. an MBean. + */ private DefaultMutableTreeNode createDnNode( Dn dn, Token token, XMBean xmbean) { DefaultMutableTreeNode node = new ComparableDefaultMutableTreeNode(); @@ -405,38 +445,36 @@ XNodeInfo userObject = new XNodeInfo(Type.MBEAN, data, label, xmbean.getObjectName().toString()); node.setUserObject(userObject); - XMBeanInfo.loadInfo(node); return node; } - //creates a node with the token value, call for each non domain sub - //dn token + /** + * Creates the node corresponding to a subDn, i.e. a non-MBean + * intermediate node. + */ private DefaultMutableTreeNode createSubDnNode(Dn dn, Token token) { DefaultMutableTreeNode node = new ComparableDefaultMutableTreeNode(); - String label = isKeyValueView() ? token.toString() : - token.getValue().toString(); + String label = isKeyValueView() ? token.getTokenValue() : token.getValue(); XNodeInfo userObject = - new XNodeInfo(Type.NONMBEAN, label, label, token.toString()); + new XNodeInfo(Type.NONMBEAN, label, label, token.getTokenValue()); node.setUserObject(userObject); return node; } private Object createNodeValue(XMBean xmbean, Token token) { - String label = isKeyValueView() ? token.toString() : - token.getValue().toString(); + String label = isKeyValueView() ? token.getTokenValue() : token.getValue(); xmbean.setText(label); return xmbean; } /** - * Parses MBean ObjectName comma-separated properties string and put the - * individual key/value pairs into the map. Key order in the properties + * Parses the MBean ObjectName comma-separated properties string and puts + * the individual key/value pairs into the map. Key order in the properties * string is preserved by the map. */ - private Map extractKeyValuePairs( - String properties, ObjectName mbean) { - String props = properties; - Map map = new LinkedHashMap(); + private static Map extractKeyValuePairs( + String props, ObjectName mbean) { + Map map = new LinkedHashMap(); int eq = props.indexOf("="); while (eq != -1) { String key = props.substring(0, eq); @@ -461,9 +499,9 @@ * in the comma-separated key property list does not apply to the given * MBean then it will be discarded. */ - private String getKeyPropertyListString(ObjectName mbean) { + private static String getKeyPropertyListString(ObjectName mbean) { String props = mbean.getKeyPropertyListString(); - Map map = extractKeyValuePairs(props, mbean); + Map map = extractKeyValuePairs(props, mbean); StringBuilder sb = new StringBuilder(); // Add the key/value pairs to the buffer following the // key order defined by the "orderedKeyPropertyList" @@ -474,7 +512,7 @@ } } // Add the remaining key/value pairs to the buffer - for (Map.Entry entry : map.entrySet()) { + for (Map.Entry entry : map.entrySet()) { sb.append(entry.getKey() + "=" + entry.getValue() + ","); } String orderedKeyPropertyListString = sb.toString(); @@ -483,67 +521,158 @@ return orderedKeyPropertyListString; } - /** - * Builds the Dn for the given MBean. - */ - private Dn buildDn(ObjectName mbean) { - - String domain = mbean.getDomain(); - String globalDn = getKeyPropertyListString(mbean); - - Dn dn = buildDn(domain, globalDn, mbean); - - //update the Dn tokens to add the domain - dn.updateDn(); - - //reverse the Dn (from leaf to root) - dn.reverseOrder(); - - //compute the hashDn - dn.computeHashDn(); - - return dn; - } - - /** - * Builds the Dn for the given MBean. - */ - private Dn buildDn(String domain, String globalDn, ObjectName mbean) { - Dn dn = new Dn(domain, globalDn); - String keyDn = "no_key"; - if (isTreeView()) { - String props = globalDn; - Map map = extractKeyValuePairs(props, mbean); - for (Map.Entry entry : map.entrySet()) { - dn.addToken(new Token(keyDn, - entry.getKey() + "=" + entry.getValue())); - } - } else { - //flat view - dn.addToken(new Token(keyDn, "properties=" + globalDn)); - } - return dn; - } - - // - //utility objects - // - - public static class ComparableDefaultMutableTreeNode - extends DefaultMutableTreeNode - implements Comparable { - public int compareTo(DefaultMutableTreeNode node) { - return (this.toString().compareTo(node.toString())); + // Call on EDT + public void addMetadataNodes(DefaultMutableTreeNode node) { + XMBean mbean = (XMBean) ((XNodeInfo) node.getUserObject()).getData(); + DefaultTreeModel model = (DefaultTreeModel) getModel(); + MBeanInfoNodesSwingWorker sw = + new MBeanInfoNodesSwingWorker(model, node, mbean); + if (sw != null) { + sw.execute(); } } - // - //tree preferences - // + private static class MBeanInfoNodesSwingWorker + extends SwingWorker { + + private final DefaultTreeModel model; + private final DefaultMutableTreeNode node; + private final XMBean mbean; + + public MBeanInfoNodesSwingWorker( + DefaultTreeModel model, + DefaultMutableTreeNode node, + XMBean mbean) { + this.model = model; + this.node = node; + this.mbean = mbean; + } + + @Override + public Object[] doInBackground() throws InstanceNotFoundException, + IntrospectionException, ReflectionException, IOException { + Object result[] = new Object[2]; + // Retrieve MBeanInfo for this MBean + result[0] = mbean.getMBeanInfo(); + // Check if this MBean is a notification emitter + result[1] = mbean.isBroadcaster(); + return result; + } + + @Override + protected void done() { + try { + Object result[] = get(); + MBeanInfo mbeanInfo = (MBeanInfo) result[0]; + Boolean isBroadcaster = (Boolean) result[1]; + if (mbeanInfo != null) { + addMBeanInfoNodes(model, node, mbean, mbeanInfo, isBroadcaster); + } + } catch (Exception e) { + Throwable t = Utils.getActualException(e); + if (JConsole.isDebug()) { + t.printStackTrace(); + } + } + } + + // Call on EDT + private void addMBeanInfoNodes( + DefaultTreeModel tree, DefaultMutableTreeNode node, + XMBean mbean, MBeanInfo mbeanInfo, Boolean isBroadcaster) { + MBeanAttributeInfo[] ai = mbeanInfo.getAttributes(); + MBeanOperationInfo[] oi = mbeanInfo.getOperations(); + MBeanNotificationInfo[] ni = mbeanInfo.getNotifications(); + + // Insert the Attributes/Operations/Notifications metadata nodes as + // the three first children of this MBean node. This is only useful + // when this MBean node denotes an MBean but it's not a leaf in the + // MBean tree + // + int childIndex = 0; - private boolean treeView; - private boolean treeViewInit = false; - public boolean isTreeView() { + // MBeanAttributeInfo node + // + if (ai != null && ai.length > 0) { + DefaultMutableTreeNode attributes = new DefaultMutableTreeNode(); + XNodeInfo attributesUO = new XNodeInfo(Type.ATTRIBUTES, mbean, + Resources.getText("Attributes"), null); + attributes.setUserObject(attributesUO); + node.insert(attributes, childIndex++); + for (MBeanAttributeInfo mbai : ai) { + DefaultMutableTreeNode attribute = new DefaultMutableTreeNode(); + XNodeInfo attributeUO = new XNodeInfo(Type.ATTRIBUTE, + new Object[]{mbean, mbai}, mbai.getName(), null); + attribute.setUserObject(attributeUO); + attribute.setAllowsChildren(false); + attributes.add(attribute); + } + } + // MBeanOperationInfo node + // + if (oi != null && oi.length > 0) { + DefaultMutableTreeNode operations = new DefaultMutableTreeNode(); + XNodeInfo operationsUO = new XNodeInfo(Type.OPERATIONS, mbean, + Resources.getText("Operations"), null); + operations.setUserObject(operationsUO); + node.insert(operations, childIndex++); + for (MBeanOperationInfo mboi : oi) { + // Compute the operation's tool tip text: + // "operationname(param1type,param2type,...)" + // + StringBuilder sb = new StringBuilder(); + for (MBeanParameterInfo mbpi : mboi.getSignature()) { + sb.append(mbpi.getType() + ","); + } + String signature = sb.toString(); + if (signature.length() > 0) { + // Remove the trailing ',' + // + signature = signature.substring(0, signature.length() - 1); + } + String toolTipText = mboi.getName() + "(" + signature + ")"; + // Create operation node + // + DefaultMutableTreeNode operation = new DefaultMutableTreeNode(); + XNodeInfo operationUO = new XNodeInfo(Type.OPERATION, + new Object[]{mbean, mboi}, mboi.getName(), toolTipText); + operation.setUserObject(operationUO); + operation.setAllowsChildren(false); + operations.add(operation); + } + } + // MBeanNotificationInfo node + // + if (isBroadcaster != null && isBroadcaster.booleanValue()) { + DefaultMutableTreeNode notifications = new DefaultMutableTreeNode(); + XNodeInfo notificationsUO = new XNodeInfo(Type.NOTIFICATIONS, mbean, + Resources.getText("Notifications"), null); + notifications.setUserObject(notificationsUO); + node.insert(notifications, childIndex++); + if (ni != null && ni.length > 0) { + for (MBeanNotificationInfo mbni : ni) { + DefaultMutableTreeNode notification = + new DefaultMutableTreeNode(); + XNodeInfo notificationUO = new XNodeInfo(Type.NOTIFICATION, + mbni, mbni.getName(), null); + notification.setUserObject(notificationUO); + notification.setAllowsChildren(false); + notifications.add(notification); + } + } + } + // Update tree model + // + model.reload(node); + } + } + // + // Tree preferences + // + private static boolean treeView; + private static boolean treeViewInit = false; + + private static boolean isTreeView() { if (!treeViewInit) { treeView = getTreeViewValue(); treeViewInit = true; @@ -551,170 +680,136 @@ return treeView; } - private boolean getTreeViewValue() { - String treeView = System.getProperty("treeView"); - return ((treeView == null) ? true : !(treeView.equals("false"))); + private static boolean getTreeViewValue() { + String tv = System.getProperty("treeView"); + return ((tv == null) ? true : !(tv.equals("false"))); } - // - //MBean key-value preferences + // MBean key-value preferences // + private boolean keyValueView = Boolean.getBoolean("keyValueView"); - private boolean keyValueView = Boolean.getBoolean("keyValueView"); - public boolean isKeyValueView() { + private boolean isKeyValueView() { return keyValueView; } // - //utility classes + // Utility classes // + private static class ComparableDefaultMutableTreeNode + extends DefaultMutableTreeNode + implements Comparable { - public static class Dn { + public int compareTo(DefaultMutableTreeNode node) { + return (this.toString().compareTo(node.toString())); + } + } + private static class Dn implements Comparable { + + private ObjectName mbean; private String domain; - private String dn; + private String keyPropertyList; private String hashDn; - private ArrayList tokens = new ArrayList(); + private List tokens = new ArrayList(); + + public Dn(ObjectName mbean) { + this.mbean = mbean; + this.domain = mbean.getDomain(); + this.keyPropertyList = getKeyPropertyListString(mbean); - public Dn(String domain, String dn) { - this.domain = domain; - this.dn = dn; + if (isTreeView()) { + // Tree view + Map map = + extractKeyValuePairs(keyPropertyList, mbean); + for (Map.Entry entry : map.entrySet()) { + tokens.add(new Token("key", entry.getKey() + "=" + entry.getValue())); + } + } else { + // Flat view + tokens.add(new Token("key", "properties=" + keyPropertyList)); + } + + // Add the domain as the first token in the Dn + tokens.add(0, new Token("domain", "domain=" + domain)); + + // Reverse the Dn (from leaf to root) + Collections.reverse(tokens); + + // Compute hash for Dn + computeHashDn(); } - public void clearTokens() { - tokens.clear(); - } - - public void addToken(Token token) { - tokens.add(token); + public ObjectName getObjectName() { + return mbean; } - public void addToken(int index, Token token) { - tokens.add(index, token); + public String getDomain() { + return domain; } - public void setToken(int index, Token token) { - tokens.set(index, token); - } - - public void removeToken(int index) { - tokens.remove(index); + public String getKeyPropertyList() { + return keyPropertyList; } public Token getToken(int index) { return tokens.get(index); } - public void reverseOrder() { - ArrayList newOrder = new ArrayList(tokens.size()); - for (int i = tokens.size() - 1; i >= 0; i--) { - newOrder.add(tokens.get(i)); - } - tokens = newOrder; - } - - public int size() { + public int getTokenCount() { return tokens.size(); } - public String getDomain() { - return domain; - } - - public String getDn() { - return dn; - } - public String getHashDn() { return hashDn; } public String getHashKey(Token token) { - final int begin = getHashDn().indexOf(token.getHashToken()); - return getHashDn().substring(begin, getHashDn().length()); + final int begin = hashDn.indexOf(token.getTokenValue()); + return hashDn.substring(begin, hashDn.length()); } - public void computeHashDn() { - final StringBuilder hashDn = new StringBuilder(); - final int tokensSize = tokens.size(); - for (int i = 0; i < tokensSize; i++) { - Token token = tokens.get(i); - String hashToken = token.getHashToken(); - if (hashToken == null) { - hashToken = token.getToken() + (tokensSize - i); - token.setHashToken(hashToken); - } - hashDn.append(hashToken); - hashDn.append(","); + private void computeHashDn() { + if (tokens.isEmpty()) { + return; } - if (tokensSize > 0) { - this.hashDn = hashDn.substring(0, hashDn.length() - 1); - } else { - this.hashDn = ""; + final StringBuilder hdn = new StringBuilder(); + for (int i = 0; i < tokens.size(); i++) { + hdn.append(tokens.get(i).getTokenValue()); + hdn.append(","); } + hashDn = hdn.substring(0, hdn.length() - 1); } - /** - * Adds the domain as the first token in the Dn. - */ - public void updateDn() { - addToken(0, new Token("domain", "domain=" + getDomain())); + @Override + public String toString() { + return domain + ":" + keyPropertyList; } - public String toString() { - return tokens.toString(); + public int compareTo(Dn dn) { + return this.toString().compareTo(dn.toString()); } } - public static class Token { + private static class Token { - private String keyDn; - private String token; - private String hashToken; + private String tokenType; + private String tokenValue; private String key; private String value; - public Token(String keyDn, String token) { - this.keyDn = keyDn; - this.token = token; - buildKeyValue(); - } - - public Token(String keyDn, String token, String hashToken) { - this.keyDn = keyDn; - this.token = token; - this.hashToken = hashToken; + public Token(String tokenType, String tokenValue) { + this.tokenType = tokenType; + this.tokenValue = tokenValue; buildKeyValue(); } - public String getKeyDn() { - return keyDn; - } - - public String getToken() { - return token; - } - - public void setValue(String value) { - this.value = value; - this.token = key + "=" + value; + public String getTokenType() { + return tokenType; } - public void setKey(String key) { - this.key = key; - this.token = key + "=" + value; - } - - public void setKeyDn(String keyDn) { - this.keyDn = keyDn; - } - - public void setHashToken(String hashToken) { - this.hashToken = hashToken; - } - - public String getHashToken() { - return hashToken; + public String getTokenValue() { + return tokenValue; } public String getKey() { @@ -725,26 +820,14 @@ return value; } - public String toString(){ - return getToken(); - } - - public boolean equals(Object object) { - if (object instanceof Token) { - return token.equals(((Token) object)); + private void buildKeyValue() { + int index = tokenValue.indexOf("="); + if (index < 0) { + key = tokenValue; + value = tokenValue; } else { - return false; - } - } - - private void buildKeyValue() { - int index = token.indexOf("="); - if (index < 0) { - key = token; - value = token; - } else { - key = token.substring(0, index); - value = token.substring(index + 1, token.length()); + key = tokenValue.substring(0, index); + value = tokenValue.substring(index + 1, tokenValue.length()); } } } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/classes/sun/tools/native2ascii/N2AFilter.java --- a/jdk/src/share/classes/sun/tools/native2ascii/N2AFilter.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/classes/sun/tools/native2ascii/N2AFilter.java Tue Mar 11 23:37:02 2008 -0700 @@ -42,7 +42,7 @@ public void write(char b) throws IOException { char[] buf = new char[1]; - buf[0] = (char)b; + buf[0] = b; write(buf, 0, 1); } diff -r 6266821dc652 -r 842a7d676774 jdk/src/share/native/java/io/io_util.c --- a/jdk/src/share/native/java/io/io_util.c Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/share/native/java/io/io_util.c Tue Mar 11 23:37:02 2008 -0700 @@ -40,7 +40,7 @@ char ret; FD fd = GET_FD(this, fid); if (fd == -1) { - JNU_ThrowIOException (env, "Stream Closed"); + JNU_ThrowIOException(env, "Stream Closed"); return -1; } nread = IO_Read(fd, &ret, 1); @@ -94,8 +94,8 @@ fd = GET_FD(this, fid); if (fd == -1) { - JNU_ThrowIOException (env, "Stream Closed"); - return -1; + JNU_ThrowIOException(env, "Stream Closed"); + return -1; } nread = IO_Read(fd, buf, len); @@ -121,7 +121,7 @@ int n; FD fd = GET_FD(this, fid); if (fd == -1) { - JNU_ThrowIOException (env, "Stream Closed"); + JNU_ThrowIOException(env, "Stream Closed"); return; } n = IO_Write(fd, &c, 1); @@ -172,8 +172,8 @@ while (len > 0) { fd = GET_FD(this, fid); if (fd == -1) { - JNU_ThrowIOException (env, "Stream Closed"); - return; + JNU_ThrowIOException(env, "Stream Closed"); + break; } n = IO_Write(fd, buf+off, len); if (n == JVM_IO_ERR) { diff -r 6266821dc652 -r 842a7d676774 jdk/src/solaris/bin/java_md.c --- a/jdk/src/solaris/bin/java_md.c Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/solaris/bin/java_md.c Tue Mar 11 23:37:02 2008 -0700 @@ -1299,12 +1299,6 @@ AddOption(pid_prop_str, NULL); #endif } -void -SetJavaw() -{ - /* noop on UNIX */ - return; -} jboolean IsJavaw() @@ -1312,3 +1306,9 @@ /* noop on UNIX */ return JNI_FALSE; } + +void +InitLauncher(jboolean javaw) +{ + JLI_SetTraceLauncher(); +} diff -r 6266821dc652 -r 842a7d676774 jdk/src/solaris/classes/java/io/FileDescriptor.java --- a/jdk/src/solaris/classes/java/io/FileDescriptor.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/solaris/classes/java/io/FileDescriptor.java Tue Mar 11 23:37:02 2008 -0700 @@ -152,11 +152,19 @@ public int get(FileDescriptor obj) { return obj.fd; } + + public void setHandle(FileDescriptor obj, long handle) { + throw new UnsupportedOperationException(); + } + + public long getHandle(FileDescriptor obj) { + throw new UnsupportedOperationException(); + } } ); } - // pacakge private methods used by FIS,FOS and RAF + // package private methods used by FIS, FOS and RAF int incrementAndGetUseCount() { return useCount.incrementAndGet(); diff -r 6266821dc652 -r 842a7d676774 jdk/src/solaris/classes/java/lang/ProcessImpl.java --- a/jdk/src/solaris/classes/java/lang/ProcessImpl.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/solaris/classes/java/lang/ProcessImpl.java Tue Mar 11 23:37:02 2008 -0700 @@ -26,7 +26,10 @@ package java.lang; import java.io.IOException; -import java.lang.Process; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.lang.ProcessBuilder.Redirect; +import java.lang.ProcessBuilder.Redirect; /** * This class is for the exclusive use of ProcessBuilder.start() to @@ -36,6 +39,9 @@ * @since 1.5 */ final class ProcessImpl { + private static final sun.misc.JavaIOFileDescriptorAccess fdAccess + = sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess(); + private ProcessImpl() {} // Not instantiable private static byte[] toCString(String s) { @@ -54,6 +60,7 @@ static Process start(String[] cmdarray, java.util.Map environment, String dir, + ProcessBuilder.Redirect[] redirects, boolean redirectErrorStream) throws IOException { @@ -78,11 +85,61 @@ int[] envc = new int[1]; byte[] envBlock = ProcessEnvironment.toEnvironmentBlock(environment, envc); + int[] std_fds; + + FileInputStream f0 = null; + FileOutputStream f1 = null; + FileOutputStream f2 = null; + + try { + if (redirects == null) { + std_fds = new int[] { -1, -1, -1 }; + } else { + std_fds = new int[3]; + + if (redirects[0] == Redirect.PIPE) + std_fds[0] = -1; + else if (redirects[0] == Redirect.INHERIT) + std_fds[0] = 0; + else { + f0 = new FileInputStream(redirects[0].file()); + std_fds[0] = fdAccess.get(f0.getFD()); + } + + if (redirects[1] == Redirect.PIPE) + std_fds[1] = -1; + else if (redirects[1] == Redirect.INHERIT) + std_fds[1] = 1; + else { + f1 = redirects[1].toFileOutputStream(); + std_fds[1] = fdAccess.get(f1.getFD()); + } + + if (redirects[2] == Redirect.PIPE) + std_fds[2] = -1; + else if (redirects[2] == Redirect.INHERIT) + std_fds[2] = 2; + else { + f2 = redirects[2].toFileOutputStream(); + std_fds[2] = fdAccess.get(f2.getFD()); + } + } + return new UNIXProcess (toCString(cmdarray[0]), argBlock, args.length, envBlock, envc[0], toCString(dir), + std_fds, redirectErrorStream); + } finally { + // In theory, close() can throw IOException + // (although it is rather unlikely to happen here) + try { if (f0 != null) f0.close(); } + finally { + try { if (f1 != null) f1.close(); } + finally { if (f2 != null) f2.close(); } + } + } } } diff -r 6266821dc652 -r 842a7d676774 jdk/src/solaris/classes/java/lang/UNIXProcess.java.linux --- a/jdk/src/solaris/classes/java/lang/UNIXProcess.java.linux Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/solaris/classes/java/lang/UNIXProcess.java.linux Tue Mar 11 23:37:02 2008 -0700 @@ -1,5 +1,5 @@ -/* - * Copyright 1995-2006 Sun Microsystems, Inc. All Rights Reserved. +/* + * Copyright 1995-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,9 +34,9 @@ */ final class UNIXProcess extends Process { - private FileDescriptor stdin_fd; - private FileDescriptor stdout_fd; - private FileDescriptor stderr_fd; + private static final sun.misc.JavaIOFileDescriptorAccess fdAccess + = sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess(); + private int pid; private int exitcode; private boolean hasExited; @@ -48,15 +48,26 @@ /* this is for the reaping thread */ private native int waitForProcessExit(int pid); + /** + * Create a process using fork(2) and exec(2). + * + * @param std_fds array of file descriptors. Indexes 0, 1, and + * 2 correspond to standard input, standard output and + * standard error, respectively. On input, a value of -1 + * means to create a pipe to connect child and parent + * processes. On output, a value which is not -1 is the + * parent pipe fd corresponding to the pipe which has + * been created. An element of this array is -1 on input + * if and only if it is not -1 on output. + * @return the pid of the subprocess + */ private native int forkAndExec(byte[] prog, - byte[] argBlock, int argc, - byte[] envBlock, int envc, - byte[] dir, - boolean redirectErrorStream, - FileDescriptor stdin_fd, - FileDescriptor stdout_fd, - FileDescriptor stderr_fd) - throws IOException; + byte[] argBlock, int argc, + byte[] envBlock, int envc, + byte[] dir, + int[] std_fds, + boolean redirectErrorStream) + throws IOException; /* In the process constructor we wait on this gate until the process */ /* has been created. Then we return from the constructor. */ @@ -97,67 +108,82 @@ } UNIXProcess(final byte[] prog, - final byte[] argBlock, final int argc, - final byte[] envBlock, final int envc, - final byte[] dir, - final boolean redirectErrorStream) + final byte[] argBlock, final int argc, + final byte[] envBlock, final int envc, + final byte[] dir, + final int[] std_fds, + final boolean redirectErrorStream) throws IOException { - stdin_fd = new FileDescriptor(); - stdout_fd = new FileDescriptor(); - stderr_fd = new FileDescriptor(); final Gate gate = new Gate(); - /* - * For each subprocess forked a corresponding reaper thread - * is started. That thread is the only thread which waits - * for the subprocess to terminate and it doesn't hold any - * locks while doing so. This design allows waitFor() and - * exitStatus() to be safely executed in parallel (and they - * need no native code). - */ + /* + * For each subprocess forked a corresponding reaper thread + * is started. That thread is the only thread which waits + * for the subprocess to terminate and it doesn't hold any + * locks while doing so. This design allows waitFor() and + * exitStatus() to be safely executed in parallel (and they + * need no native code). + */ - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - Thread t = new Thread("process reaper") { - public void run() { + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + Thread t = new Thread("process reaper") { + public void run() { try { pid = forkAndExec(prog, - argBlock, argc, - envBlock, envc, - dir, - redirectErrorStream, - stdin_fd, stdout_fd, stderr_fd); + argBlock, argc, + envBlock, envc, + dir, + std_fds, + redirectErrorStream); } catch (IOException e) { gate.setException(e); /*remember to rethrow later*/ gate.exit(); return; } java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - stdin_stream = new BufferedOutputStream(new - FileOutputStream(stdin_fd)); - stdout_stream = new BufferedInputStream(new - FileInputStream(stdout_fd)); - stderr_stream = new FileInputStream(stderr_fd); - return null; + new java.security.PrivilegedAction() { + public Void run() { + if (std_fds[0] == -1) + stdin_stream = new ProcessBuilder.NullOutputStream(); + else { + FileDescriptor stdin_fd = new FileDescriptor(); + fdAccess.set(stdin_fd, std_fds[0]); + stdin_stream = new BufferedOutputStream( + new FileOutputStream(stdin_fd)); + } + + if (std_fds[1] == -1) + stdout_stream = new ProcessBuilder.NullInputStream(); + else { + FileDescriptor stdout_fd = new FileDescriptor(); + fdAccess.set(stdout_fd, std_fds[1]); + stdout_stream = new BufferedInputStream( + new FileInputStream(stdout_fd)); } - }); + + if (std_fds[2] == -1) + stderr_stream = new ProcessBuilder.NullInputStream(); + else { + FileDescriptor stderr_fd = new FileDescriptor(); + fdAccess.set(stderr_fd, std_fds[2]); + stderr_stream = new FileInputStream(stderr_fd); + } + + return null; }}); gate.exit(); /* exit from constructor */ - int res = waitForProcessExit(pid); - synchronized (UNIXProcess.this) { - hasExited = true; - exitcode = res; - UNIXProcess.this.notifyAll(); - } - } - }; + int res = waitForProcessExit(pid); + synchronized (UNIXProcess.this) { + hasExited = true; + exitcode = res; + UNIXProcess.this.notifyAll(); + } + } + }; t.setDaemon(true); t.start(); - return null; - } - }); + return null; }}); gate.waitForExit(); IOException e = gate.getException(); if (e != null) @@ -165,43 +191,43 @@ } public OutputStream getOutputStream() { - return stdin_stream; + return stdin_stream; } public InputStream getInputStream() { - return stdout_stream; + return stdout_stream; } public InputStream getErrorStream() { - return stderr_stream; + return stderr_stream; } public synchronized int waitFor() throws InterruptedException { while (!hasExited) { - wait(); - } - return exitcode; + wait(); + } + return exitcode; } public synchronized int exitValue() { - if (!hasExited) { - throw new IllegalThreadStateException("process hasn't exited"); - } - return exitcode; + if (!hasExited) { + throw new IllegalThreadStateException("process hasn't exited"); + } + return exitcode; } private static native void destroyProcess(int pid); public void destroy() { - // There is a risk that pid will be recycled, causing us to - // kill the wrong process! So we only terminate processes - // that appear to still be running. Even with this check, - // there is an unavoidable race condition here, but the window - // is very small, and OSes try hard to not recycle pids too - // soon, so this is quite safe. - synchronized (this) { - if (!hasExited) - destroyProcess(pid); - } + // There is a risk that pid will be recycled, causing us to + // kill the wrong process! So we only terminate processes + // that appear to still be running. Even with this check, + // there is an unavoidable race condition here, but the window + // is very small, and OSes try hard to not recycle pids too + // soon, so this is quite safe. + synchronized (this) { + if (!hasExited) + destroyProcess(pid); + } try { stdin_stream.close(); stdout_stream.close(); @@ -215,6 +241,6 @@ private static native void initIDs(); static { - initIDs(); + initIDs(); } } diff -r 6266821dc652 -r 842a7d676774 jdk/src/solaris/classes/java/lang/UNIXProcess.java.solaris --- a/jdk/src/solaris/classes/java/lang/UNIXProcess.java.solaris Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/solaris/classes/java/lang/UNIXProcess.java.solaris Tue Mar 11 23:37:02 2008 -0700 @@ -1,5 +1,5 @@ -/* - * Copyright 1995-2006 Sun Microsystems, Inc. All Rights Reserved. +/* + * Copyright 1995-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,129 +33,155 @@ */ final class UNIXProcess extends Process { - private FileDescriptor stdin_fd; - private FileDescriptor stdout_fd; - private FileDescriptor stderr_fd; - private int pid; + private static final sun.misc.JavaIOFileDescriptorAccess fdAccess + = sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess(); + + private final int pid; private int exitcode; private boolean hasExited; private OutputStream stdin_stream; - private BufferedInputStream stdout_stream; + private InputStream stdout_stream; private DeferredCloseInputStream stdout_inner_stream; - private DeferredCloseInputStream stderr_stream; + private InputStream stderr_stream; /* this is for the reaping thread */ private native int waitForProcessExit(int pid); + /** + * Create a process using fork(2) and exec(2). + * + * @param std_fds array of file descriptors. Indexes 0, 1, and + * 2 correspond to standard input, standard output and + * standard error, respectively. On input, a value of -1 + * means to create a pipe to connect child and parent + * processes. On output, a value which is not -1 is the + * parent pipe fd corresponding to the pipe which has + * been created. An element of this array is -1 on input + * if and only if it is not -1 on output. + * @return the pid of the subprocess + */ private native int forkAndExec(byte[] prog, - byte[] argBlock, int argc, - byte[] envBlock, int envc, - byte[] dir, - boolean redirectErrorStream, - FileDescriptor stdin_fd, - FileDescriptor stdout_fd, - FileDescriptor stderr_fd) - throws IOException; + byte[] argBlock, int argc, + byte[] envBlock, int envc, + byte[] dir, + int[] std_fds, + boolean redirectErrorStream) + throws IOException; UNIXProcess(final byte[] prog, - final byte[] argBlock, int argc, - final byte[] envBlock, int envc, - final byte[] dir, - final boolean redirectErrorStream) + final byte[] argBlock, int argc, + final byte[] envBlock, int envc, + final byte[] dir, + final int[] std_fds, + final boolean redirectErrorStream) throws IOException { - stdin_fd = new FileDescriptor(); - stdout_fd = new FileDescriptor(); - stderr_fd = new FileDescriptor(); + pid = forkAndExec(prog, + argBlock, argc, + envBlock, envc, + dir, + std_fds, + redirectErrorStream); - pid = forkAndExec(prog, - argBlock, argc, - envBlock, envc, - dir, - redirectErrorStream, - stdin_fd, stdout_fd, stderr_fd); + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { public Void run() { + if (std_fds[0] == -1) + stdin_stream = new ProcessBuilder.NullOutputStream(); + else { + FileDescriptor stdin_fd = new FileDescriptor(); + fdAccess.set(stdin_fd, std_fds[0]); + stdin_stream = new BufferedOutputStream( + new FileOutputStream(stdin_fd)); + } - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - stdin_stream - = new BufferedOutputStream(new FileOutputStream(stdin_fd)); - stdout_inner_stream = new DeferredCloseInputStream(stdout_fd); - stdout_stream = new BufferedInputStream(stdout_inner_stream); - stderr_stream = new DeferredCloseInputStream(stderr_fd); - return null; - } - }); + if (std_fds[1] == -1) + stdout_stream = new ProcessBuilder.NullInputStream(); + else { + FileDescriptor stdout_fd = new FileDescriptor(); + fdAccess.set(stdout_fd, std_fds[1]); + stdout_inner_stream = new DeferredCloseInputStream(stdout_fd); + stdout_stream = new BufferedInputStream(stdout_inner_stream); + } - /* - * For each subprocess forked a corresponding reaper thread - * is started. That thread is the only thread which waits - * for the subprocess to terminate and it doesn't hold any - * locks while doing so. This design allows waitFor() and - * exitStatus() to be safely executed in parallel (and they - * need no native code). - */ + if (std_fds[2] == -1) + stderr_stream = new ProcessBuilder.NullInputStream(); + else { + FileDescriptor stderr_fd = new FileDescriptor(); + fdAccess.set(stderr_fd, std_fds[2]); + stderr_stream = new DeferredCloseInputStream(stderr_fd); + } + + return null; }}); - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - Thread t = new Thread("process reaper") { - public void run() { - int res = waitForProcessExit(pid); - synchronized (UNIXProcess.this) { - hasExited = true; - exitcode = res; - UNIXProcess.this.notifyAll(); - } - } - }; - t.setDaemon(true); - t.start(); - return null; - } - }); + /* + * For each subprocess forked a corresponding reaper thread + * is started. That thread is the only thread which waits + * for the subprocess to terminate and it doesn't hold any + * locks while doing so. This design allows waitFor() and + * exitStatus() to be safely executed in parallel (and they + * need no native code). + */ + + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { public Void run() { + Thread t = new Thread("process reaper") { + public void run() { + int res = waitForProcessExit(pid); + synchronized (UNIXProcess.this) { + hasExited = true; + exitcode = res; + UNIXProcess.this.notifyAll(); + } + } + }; + t.setDaemon(true); + t.start(); + return null; }}); } public OutputStream getOutputStream() { - return stdin_stream; + return stdin_stream; } public InputStream getInputStream() { - return stdout_stream; + return stdout_stream; } public InputStream getErrorStream() { - return stderr_stream; + return stderr_stream; } public synchronized int waitFor() throws InterruptedException { while (!hasExited) { - wait(); - } - return exitcode; + wait(); + } + return exitcode; } public synchronized int exitValue() { - if (!hasExited) { - throw new IllegalThreadStateException("process hasn't exited"); - } - return exitcode; + if (!hasExited) { + throw new IllegalThreadStateException("process hasn't exited"); + } + return exitcode; } private static native void destroyProcess(int pid); public synchronized void destroy() { - // There is a risk that pid will be recycled, causing us to - // kill the wrong process! So we only terminate processes - // that appear to still be running. Even with this check, - // there is an unavoidable race condition here, but the window - // is very small, and OSes try hard to not recycle pids too - // soon, so this is quite safe. - if (!hasExited) - destroyProcess(pid); - try { + // There is a risk that pid will be recycled, causing us to + // kill the wrong process! So we only terminate processes + // that appear to still be running. Even with this check, + // there is an unavoidable race condition here, but the window + // is very small, and OSes try hard to not recycle pids too + // soon, so this is quite safe. + if (!hasExited) + destroyProcess(pid); + try { stdin_stream.close(); - stdout_inner_stream.closeDeferred(stdout_stream); - stderr_stream.closeDeferred(stderr_stream); + if (stdout_inner_stream != null) + stdout_inner_stream.closeDeferred(stdout_stream); + if (stderr_stream instanceof DeferredCloseInputStream) + ((DeferredCloseInputStream) stderr_stream) + .closeDeferred(stderr_stream); } catch (IOException e) { // ignore } @@ -172,99 +198,99 @@ // (EOF) as they did before. // private static class DeferredCloseInputStream - extends FileInputStream + extends FileInputStream { - private DeferredCloseInputStream(FileDescriptor fd) { - super(fd); - } + private DeferredCloseInputStream(FileDescriptor fd) { + super(fd); + } - private Object lock = new Object(); // For the following fields - private boolean closePending = false; - private int useCount = 0; - private InputStream streamToClose; + private Object lock = new Object(); // For the following fields + private boolean closePending = false; + private int useCount = 0; + private InputStream streamToClose; - private void raise() { - synchronized (lock) { - useCount++; - } - } + private void raise() { + synchronized (lock) { + useCount++; + } + } - private void lower() throws IOException { - synchronized (lock) { - useCount--; - if (useCount == 0 && closePending) { - streamToClose.close(); - } - } - } + private void lower() throws IOException { + synchronized (lock) { + useCount--; + if (useCount == 0 && closePending) { + streamToClose.close(); + } + } + } - // stc is the actual stream to be closed; it might be this object, or - // it might be an upstream object for which this object is downstream. - // - private void closeDeferred(InputStream stc) throws IOException { - synchronized (lock) { - if (useCount == 0) { - stc.close(); - } else { - closePending = true; - streamToClose = stc; - } - } - } + // stc is the actual stream to be closed; it might be this object, or + // it might be an upstream object for which this object is downstream. + // + private void closeDeferred(InputStream stc) throws IOException { + synchronized (lock) { + if (useCount == 0) { + stc.close(); + } else { + closePending = true; + streamToClose = stc; + } + } + } - public void close() throws IOException { - synchronized (lock) { - useCount = 0; - closePending = false; - } - super.close(); - } + public void close() throws IOException { + synchronized (lock) { + useCount = 0; + closePending = false; + } + super.close(); + } - public int read() throws IOException { - raise(); - try { - return super.read(); - } finally { - lower(); - } - } + public int read() throws IOException { + raise(); + try { + return super.read(); + } finally { + lower(); + } + } - public int read(byte[] b) throws IOException { - raise(); - try { - return super.read(b); - } finally { - lower(); - } - } + public int read(byte[] b) throws IOException { + raise(); + try { + return super.read(b); + } finally { + lower(); + } + } - public int read(byte[] b, int off, int len) throws IOException { - raise(); - try { - return super.read(b, off, len); - } finally { - lower(); - } - } + public int read(byte[] b, int off, int len) throws IOException { + raise(); + try { + return super.read(b, off, len); + } finally { + lower(); + } + } - public long skip(long n) throws IOException { - raise(); - try { - return super.skip(n); - } finally { - lower(); - } - } + public long skip(long n) throws IOException { + raise(); + try { + return super.skip(n); + } finally { + lower(); + } + } - public int available() throws IOException { - raise(); - try { - return super.available(); - } finally { - lower(); - } - } + public int available() throws IOException { + raise(); + try { + return super.available(); + } finally { + lower(); + } + } } @@ -272,6 +298,6 @@ private static native void initIDs(); static { - initIDs(); + initIDs(); } } diff -r 6266821dc652 -r 842a7d676774 jdk/src/solaris/classes/java/util/prefs/FileSystemPreferences.java --- a/jdk/src/solaris/classes/java/util/prefs/FileSystemPreferences.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/solaris/classes/java/util/prefs/FileSystemPreferences.java Tue Mar 11 23:37:02 2008 -0700 @@ -52,14 +52,10 @@ * Sync interval in seconds. */ private static final int SYNC_INTERVAL = Math.max(1, - Integer.parseInt((String) - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - return System.getProperty("java.util.prefs.syncInterval", - "30"); - } - }))); - + Integer.parseInt( + AccessController.doPrivileged( + new sun.security.action.GetPropertyAction( + "java.util.prefs.syncInterval", "30")))); /** * Returns logger for error messages. Backing store exceptions are logged at @@ -103,8 +99,8 @@ } private static void setupUserRoot() { - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { userRootDir = new File(System.getProperty("java.util.prefs.userRoot", System.getProperty("user.home")), ".java/.userPrefs"); @@ -164,9 +160,9 @@ } private static void setupSystemRoot() { - AccessController.doPrivileged( new PrivilegedAction() { - public Object run() { - String systemPrefsDirName = (String) + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + String systemPrefsDirName = System.getProperty("java.util.prefs.systemRoot","/etc/.java"); systemRootDir = new File(systemPrefsDirName, ".systemPrefs"); @@ -322,7 +318,7 @@ * corresponding disk file (prefsFile) by the sync operation. The initial * value is read *without* acquiring the file-lock. */ - private Map prefsCache = null; + private Map prefsCache = null; /** * The last modification time of the file backing this node at the time @@ -358,7 +354,7 @@ * log against that map. The resulting map is then written back * to the disk. */ - final List changeLog = new ArrayList(); + final List changeLog = new ArrayList(); /** * Represents a change to a preference. @@ -424,7 +420,7 @@ */ private void replayChanges() { for (int i = 0, n = changeLog.size(); i() { + public Void run() { Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { syncTimer.cancel(); @@ -503,15 +499,15 @@ dir = new File(parent.dir, dirName(name)); prefsFile = new File(dir, "prefs.xml"); tmpFile = new File(dir, "prefs.tmp"); - AccessController.doPrivileged( new PrivilegedAction() { - public Object run() { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { newNode = !dir.exists(); return null; } }); if (newNode) { // These 2 things guarantee node will get wrtten at next flush/sync - prefsCache = new TreeMap(); + prefsCache = new TreeMap(); nodeCreate = new NodeCreate(); changeLog.add(nodeCreate); } @@ -529,7 +525,7 @@ protected String getSpi(String key) { initCacheIfNecessary(); - return (String) prefsCache.get(key); + return prefsCache.get(key); } protected void removeSpi(String key) { @@ -554,7 +550,7 @@ loadCache(); } catch(Exception e) { // assert lastSyncTime == 0; - prefsCache = new TreeMap(); + prefsCache = new TreeMap(); } } @@ -568,9 +564,10 @@ */ private void loadCache() throws BackingStoreException { try { - AccessController.doPrivileged( new PrivilegedExceptionAction() { - public Object run() throws BackingStoreException { - Map m = new TreeMap(); + AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public Void run() throws BackingStoreException { + Map m = new TreeMap(); long newLastSyncTime = 0; try { newLastSyncTime = prefsFile.lastModified(); @@ -584,7 +581,7 @@ prefsFile.renameTo( new File( prefsFile.getParentFile(), "IncorrectFormatPrefs.xml")); - m = new TreeMap(); + m = new TreeMap(); } else if (e instanceof FileNotFoundException) { getLogger().warning("Prefs file removed in background " + prefsFile.getPath()); @@ -614,8 +611,9 @@ */ private void writeBackCache() throws BackingStoreException { try { - AccessController.doPrivileged( new PrivilegedExceptionAction() { - public Object run() throws BackingStoreException { + AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public Void run() throws BackingStoreException { try { if (!dir.exists() && !dir.mkdirs()) throw new BackingStoreException(dir + @@ -641,15 +639,14 @@ protected String[] keysSpi() { initCacheIfNecessary(); - return (String[]) - prefsCache.keySet().toArray(new String[prefsCache.size()]); + return prefsCache.keySet().toArray(new String[prefsCache.size()]); } protected String[] childrenNamesSpi() { - return (String[]) - AccessController.doPrivileged( new PrivilegedAction() { - public Object run() { - List result = new ArrayList(); + return AccessController.doPrivileged( + new PrivilegedAction() { + public String[] run() { + List result = new ArrayList(); File[] dirContents = dir.listFiles(); if (dirContents != null) { for (int i = 0; i < dirContents.length; i++) @@ -685,8 +682,9 @@ */ protected void removeNodeSpi() throws BackingStoreException { try { - AccessController.doPrivileged( new PrivilegedExceptionAction() { - public Object run() throws BackingStoreException { + AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public Void run() throws BackingStoreException { if (changeLog.contains(nodeCreate)) { changeLog.remove(nodeCreate); nodeCreate = null; @@ -731,8 +729,9 @@ if (!lockFile(shared)) throw(new BackingStoreException("Couldn't get file lock.")); final Long newModTime = - (Long) AccessController.doPrivileged( new PrivilegedAction() { - public Object run() { + AccessController.doPrivileged( + new PrivilegedAction() { + public Long run() { long nmt; if (isUserNode()) { nmt = userRootModFile.lastModified(); @@ -746,8 +745,8 @@ }); try { super.sync(); - AccessController.doPrivileged( new PrivilegedAction() { - public Object run() { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { if (isUserNode()) { userRootModTime = newModTime.longValue() + 1000; userRootModFile.setLastModified(userRootModTime); @@ -766,8 +765,9 @@ protected void syncSpi() throws BackingStoreException { try { - AccessController.doPrivileged( new PrivilegedExceptionAction() { - public Object run() throws BackingStoreException { + AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public Void run() throws BackingStoreException { syncSpiPrivileged(); return null; } @@ -794,7 +794,7 @@ } else if (lastSyncTime != 0 && !dir.exists()) { // This node was removed in the background. Playback any changes // against a virgin (empty) Map. - prefsCache = new TreeMap(); + prefsCache = new TreeMap(); replayChanges(); } if (!changeLog.isEmpty()) { diff -r 6266821dc652 -r 842a7d676774 jdk/src/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java --- a/jdk/src/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java Tue Mar 11 23:37:02 2008 -0700 @@ -217,8 +217,7 @@ Updator u = null; while ((u = updateList.poll()) != null) { // First add pollfd struct to clear out this fd - putPollFD(updatePollArray, index, u.fd, - (short)POLLREMOVE); + putPollFD(updatePollArray, index, u.fd, POLLREMOVE); index++; // Now add pollfd to update this fd, if necessary if (u.mask != POLLREMOVE) { diff -r 6266821dc652 -r 842a7d676774 jdk/src/solaris/classes/sun/security/provider/NativePRNG.java --- a/jdk/src/solaris/classes/sun/security/provider/NativePRNG.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/solaris/classes/sun/security/provider/NativePRNG.java Tue Mar 11 23:37:02 2008 -0700 @@ -71,8 +71,9 @@ private static final RandomIO INSTANCE = initIO(); private static RandomIO initIO() { - Object o = AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + return AccessController.doPrivileged( + new PrivilegedAction() { + public RandomIO run() { File randomFile = new File(NAME_RANDOM); if (randomFile.exists() == false) { return null; @@ -88,7 +89,6 @@ } } }); - return (RandomIO)o; } // return whether the NativePRNG is available diff -r 6266821dc652 -r 842a7d676774 jdk/src/solaris/native/java/io/FileOutputStream_md.c --- a/jdk/src/solaris/native/java/io/FileOutputStream_md.c Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/solaris/native/java/io/FileOutputStream_md.c Tue Mar 11 23:37:02 2008 -0700 @@ -53,13 +53,10 @@ */ JNIEXPORT void JNICALL -Java_java_io_FileOutputStream_open(JNIEnv *env, jobject this, jstring path) { - fileOpen(env, this, path, fos_fd, O_WRONLY | O_CREAT | O_TRUNC); -} - -JNIEXPORT void JNICALL -Java_java_io_FileOutputStream_openAppend(JNIEnv *env, jobject this, jstring path) { - fileOpen(env, this, path, fos_fd, O_WRONLY | O_CREAT | O_APPEND); +Java_java_io_FileOutputStream_open(JNIEnv *env, jobject this, + jstring path, jboolean append) { + fileOpen(env, this, path, fos_fd, + O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC)); } JNIEXPORT void JNICALL diff -r 6266821dc652 -r 842a7d676774 jdk/src/solaris/native/java/lang/UNIXProcess_md.c --- a/jdk/src/solaris/native/java/lang/UNIXProcess_md.c Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/solaris/native/java/lang/UNIXProcess_md.c Tue Mar 11 23:37:02 2008 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1995-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -479,6 +479,37 @@ close(fd); } +/* + * Reads nbyte bytes from file descriptor fd into buf, + * The read operation is retried in case of EINTR or partial reads. + * + * Returns number of bytes read (normally nbyte, but may be less in + * case of EOF). In case of read errors, returns -1 and sets errno. + */ +static ssize_t +readFully(int fd, void *buf, size_t nbyte) +{ + ssize_t remaining = nbyte; + for (;;) { + ssize_t n = read(fd, buf, remaining); + if (n == 0) { + return nbyte - remaining; + } else if (n > 0) { + remaining -= n; + if (remaining <= 0) + return nbyte; + /* We were interrupted in the middle of reading the bytes. + * Unlikely, but possible. */ + buf = (void *) (((char *)buf) + n); + } else if (errno == EINTR) { + /* Strange signals like SIGJVM1 are possible at any time. + * See http://www.dreamsongs.com/WorseIsBetter.html */ + } else { + return -1; + } + } +} + #ifndef __solaris__ #undef fork1 #define fork1() fork() @@ -491,10 +522,8 @@ jbyteArray argBlock, jint argc, jbyteArray envBlock, jint envc, jbyteArray dir, - jboolean redirectErrorStream, - jobject stdin_fd, - jobject stdout_fd, - jobject stderr_fd) + jintArray std_fds, + jboolean redirectErrorStream) { int errnum; int resultPid = -1; @@ -505,6 +534,7 @@ const char *pargBlock = getBytes(env, argBlock); const char *penvBlock = getBytes(env, envBlock); const char *pdir = getBytes(env, dir); + jint *fds = NULL; in[0] = in[1] = out[0] = out[1] = err[0] = err[1] = fail[0] = fail[1] = -1; @@ -527,9 +557,13 @@ initVectorFromBlock(envv, penvBlock, envc); } - if ((pipe(in) < 0) || - (pipe(out) < 0) || - (pipe(err) < 0) || + assert(std_fds != NULL); + fds = (*env)->GetIntArrayElements(env, std_fds, NULL); + if (fds == NULL) goto Catch; + + if ((fds[0] == -1 && pipe(in) < 0) || + (fds[1] == -1 && pipe(out) < 0) || + (fds[2] == -1 && pipe(err) < 0) || (pipe(fail) < 0)) { throwIOException(env, errno, "Bad file descriptor"); goto Catch; @@ -544,23 +578,26 @@ if (resultPid == 0) { /* Child process */ - /* Close the parent sides of the pipe. - Give the child sides of the pipes the right fileno's. + /* Close the parent sides of the pipes. Closing pipe fds here is redundant, since closeDescriptors() would do it anyways, but a little paranoia is a good thing. */ + closeSafely(in[1]); + closeSafely(out[0]); + closeSafely(err[0]); + closeSafely(fail[0]); + + /* Give the child sides of the pipes the right fileno's. */ /* Note: it is possible for in[0] == 0 */ - close(in[1]); - moveDescriptor(in[0], STDIN_FILENO); - close(out[0]); - moveDescriptor(out[1], STDOUT_FILENO); - close(err[0]); + moveDescriptor(in[0] != -1 ? in[0] : fds[0], STDIN_FILENO); + moveDescriptor(out[1]!= -1 ? out[1] : fds[1], STDOUT_FILENO); + if (redirectErrorStream) { - close(err[1]); + closeSafely(err[1]); dup2(STDOUT_FILENO, STDERR_FILENO); } else { - moveDescriptor(err[1], STDERR_FILENO); + moveDescriptor(err[1] != -1 ? err[1] : fds[2], STDERR_FILENO); } - close(fail[0]); + moveDescriptor(fail[1], FAIL_FILENO); /* close everything */ @@ -600,15 +637,21 @@ /* parent process */ close(fail[1]); fail[1] = -1; /* See: WhyCantJohnnyExec */ - if (read(fail[0], &errnum, sizeof(errnum)) != 0) { + + switch (readFully(fail[0], &errnum, sizeof(errnum))) { + case 0: break; /* Exec succeeded */ + case sizeof(errnum): waitpid(resultPid, NULL, 0); throwIOException(env, errnum, "Exec failed"); goto Catch; + default: + throwIOException(env, errno, "Read failed"); + goto Catch; } - (*env)->SetIntField(env, stdin_fd, IO_fd_fdID, in [1]); - (*env)->SetIntField(env, stdout_fd, IO_fd_fdID, out[0]); - (*env)->SetIntField(env, stderr_fd, IO_fd_fdID, err[0]); + fds[0] = (in [1] != -1) ? in [1] : -1; + fds[1] = (out[0] != -1) ? out[0] : -1; + fds[2] = (err[0] != -1) ? err[0] : -1; Finally: /* Always clean up the child's side of the pipes */ @@ -628,6 +671,9 @@ releaseBytes(env, envBlock, penvBlock); releaseBytes(env, dir, pdir); + if (fds != NULL) + (*env)->ReleaseIntArrayElements(env, std_fds, fds, 0); + return resultPid; Catch: diff -r 6266821dc652 -r 842a7d676774 jdk/src/windows/bin/java_md.c --- a/jdk/src/windows/bin/java_md.c Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/windows/bin/java_md.c Tue Mar 11 23:37:02 2008 -0700 @@ -33,6 +33,7 @@ #include #include #include +#include #include #include "java.h" @@ -52,11 +53,6 @@ static jboolean _isjavaw = JNI_FALSE; -void -SetJavaw() -{ - _isjavaw = JNI_TRUE; -} jboolean IsJavaw() @@ -999,3 +995,20 @@ /* Linux only, empty on windows. */ void SetJavaLauncherPlatformProps() {} + +void +InitLauncher(boolean javaw) +{ + INITCOMMONCONTROLSEX icx; + + /* + * Required for javaw mode MessageBox output as well as for + * HotSpot -XX:+ShowMessageBoxOnError in java mode, an empty + * flag field is sufficient to perform the basic UI initialization. + */ + memset(&icx, 0, sizeof(INITCOMMONCONTROLSEX)); + icx.dwSize = sizeof(INITCOMMONCONTROLSEX); + InitCommonControlsEx(&icx); + _isjavaw = javaw; + JLI_SetTraceLauncher(); +} diff -r 6266821dc652 -r 842a7d676774 jdk/src/windows/classes/java/io/FileDescriptor.java --- a/jdk/src/windows/classes/java/io/FileDescriptor.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/windows/classes/java/io/FileDescriptor.java Tue Mar 11 23:37:02 2008 -0700 @@ -29,17 +29,14 @@ /** * Instances of the file descriptor class serve as an opaque handle - * to the underlying machine-specific structure representing an open - * file, an open socket, or another source or sink of bytes. The - * main practical use for a file descriptor is to create a - * FileInputStream or FileOutputStream to - * contain it. - *

    - * Applications should not create their own file descriptors. + * to the underlying machine-specific structure representing an + * open file, an open socket, or another source or sink of bytes. + * The main practical use for a file descriptor is to create a + * {@link FileInputStream} or {@link FileOutputStream} to contain it. + * + *

    Applications should not create their own file descriptors. * * @author Pavani Diwanji - * @see java.io.FileInputStream - * @see java.io.FileOutputStream * @since JDK1.0 */ public final class FileDescriptor { @@ -81,6 +78,14 @@ public int get(FileDescriptor obj) { return obj.fd; } + + public void setHandle(FileDescriptor obj, long handle) { + obj.handle = handle; + } + + public long getHandle(FileDescriptor obj) { + return obj.handle; + } } ); } @@ -88,7 +93,7 @@ /** * A handle to the standard input stream. Usually, this file * descriptor is not used directly, but rather via the input stream - * known as System.in. + * known as {@code System.in}. * * @see java.lang.System#in */ @@ -97,7 +102,7 @@ /** * A handle to the standard output stream. Usually, this file * descriptor is not used directly, but rather via the output stream - * known as System.out. + * known as {@code System.out}. * @see java.lang.System#out */ public static final FileDescriptor out = standardStream(1); @@ -105,7 +110,7 @@ /** * A handle to the standard error stream. Usually, this file * descriptor is not used directly, but rather via the output stream - * known as System.err. + * known as {@code System.err}. * * @see java.lang.System#err */ @@ -114,9 +119,9 @@ /** * Tests if this file descriptor object is valid. * - * @return true if the file descriptor object represents a + * @return {@code true} if the file descriptor object represents a * valid, open file, socket, or other active I/O connection; - * false otherwise. + * {@code false} otherwise. */ public boolean valid() { return ((handle != -1) || (fd != -1)); diff -r 6266821dc652 -r 842a7d676774 jdk/src/windows/classes/java/lang/ProcessImpl.java --- a/jdk/src/windows/classes/java/lang/ProcessImpl.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/windows/classes/java/lang/ProcessImpl.java Tue Mar 11 23:37:02 2008 -0700 @@ -25,7 +25,16 @@ package java.lang; -import java.io.*; +import java.io.IOException; +import java.io.File; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileDescriptor; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.lang.ProcessBuilder.Redirect; /* This class is for the exclusive use of ProcessBuilder.start() to * create new processes. @@ -35,30 +44,82 @@ */ final class ProcessImpl extends Process { + private static final sun.misc.JavaIOFileDescriptorAccess fdAccess + = sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess(); // System-dependent portion of ProcessBuilder.start() static Process start(String cmdarray[], java.util.Map environment, String dir, + ProcessBuilder.Redirect[] redirects, boolean redirectErrorStream) throws IOException { String envblock = ProcessEnvironment.toEnvironmentBlock(environment); - return new ProcessImpl(cmdarray, envblock, dir, redirectErrorStream); + + FileInputStream f0 = null; + FileOutputStream f1 = null; + FileOutputStream f2 = null; + + try { + long[] stdHandles; + if (redirects == null) { + stdHandles = new long[] { -1L, -1L, -1L }; + } else { + stdHandles = new long[3]; + + if (redirects[0] == Redirect.PIPE) + stdHandles[0] = -1L; + else if (redirects[0] == Redirect.INHERIT) + stdHandles[0] = fdAccess.getHandle(FileDescriptor.in); + else { + f0 = new FileInputStream(redirects[0].file()); + stdHandles[0] = fdAccess.getHandle(f0.getFD()); + } + + if (redirects[1] == Redirect.PIPE) + stdHandles[1] = -1L; + else if (redirects[1] == Redirect.INHERIT) + stdHandles[1] = fdAccess.getHandle(FileDescriptor.out); + else { + f1 = redirects[1].toFileOutputStream(); + stdHandles[1] = fdAccess.getHandle(f1.getFD()); + } + + if (redirects[2] == Redirect.PIPE) + stdHandles[2] = -1L; + else if (redirects[2] == Redirect.INHERIT) + stdHandles[2] = fdAccess.getHandle(FileDescriptor.err); + else { + f2 = redirects[2].toFileOutputStream(); + stdHandles[2] = fdAccess.getHandle(f2.getFD()); + } + } + + return new ProcessImpl(cmdarray, envblock, dir, + stdHandles, redirectErrorStream); + } finally { + // In theory, close() can throw IOException + // (although it is rather unlikely to happen here) + try { if (f0 != null) f0.close(); } + finally { + try { if (f1 != null) f1.close(); } + finally { if (f2 != null) f2.close(); } + } + } + } private long handle = 0; - private FileDescriptor stdin_fd; - private FileDescriptor stdout_fd; - private FileDescriptor stderr_fd; private OutputStream stdin_stream; private InputStream stdout_stream; private InputStream stderr_stream; - private ProcessImpl(String cmd[], - String envblock, - String path, - boolean redirectErrorStream) + private ProcessImpl(final String cmd[], + final String envblock, + final String path, + final long[] stdHandles, + final boolean redirectErrorStream) throws IOException { // Win32 CreateProcess requires cmd[0] to be normalized @@ -91,25 +152,39 @@ } String cmdstr = cmdbuf.toString(); - stdin_fd = new FileDescriptor(); - stdout_fd = new FileDescriptor(); - stderr_fd = new FileDescriptor(); - - handle = create(cmdstr, envblock, path, redirectErrorStream, - stdin_fd, stdout_fd, stderr_fd); + handle = create(cmdstr, envblock, path, + stdHandles, redirectErrorStream); java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - stdin_stream = - new BufferedOutputStream(new FileOutputStream(stdin_fd)); - stdout_stream = - new BufferedInputStream(new FileInputStream(stdout_fd)); - stderr_stream = - new FileInputStream(stderr_fd); - return null; + new java.security.PrivilegedAction() { + public Void run() { + if (stdHandles[0] == -1L) + stdin_stream = new ProcessBuilder.NullOutputStream(); + else { + FileDescriptor stdin_fd = new FileDescriptor(); + fdAccess.setHandle(stdin_fd, stdHandles[0]); + stdin_stream = new BufferedOutputStream( + new FileOutputStream(stdin_fd)); } - }); + + if (stdHandles[1] == -1L) + stdout_stream = new ProcessBuilder.NullInputStream(); + else { + FileDescriptor stdout_fd = new FileDescriptor(); + fdAccess.setHandle(stdout_fd, stdHandles[1]); + stdout_stream = new BufferedInputStream( + new FileInputStream(stdout_fd)); + } + + if (stdHandles[2] == -1L) + stderr_stream = new ProcessBuilder.NullInputStream(); + else { + FileDescriptor stderr_fd = new FileDescriptor(); + fdAccess.setHandle(stderr_fd, stdHandles[2]); + stderr_stream = new FileInputStream(stderr_fd); + } + + return null; }}); } public OutputStream getOutputStream() { @@ -150,13 +225,30 @@ public void destroy() { terminateProcess(handle); } private static native void terminateProcess(long handle); + /** + * Create a process using the win32 function CreateProcess. + * + * @param cmdstr the Windows commandline + * @param envblock NUL-separated, double-NUL-terminated list of + * environment strings in VAR=VALUE form + * @param dir the working directory of the process, or null if + * inheriting the current directory from the parent process + * @param stdHandles array of windows HANDLEs. Indexes 0, 1, and + * 2 correspond to standard input, standard output and + * standard error, respectively. On input, a value of -1 + * means to create a pipe to connect child and parent + * processes. On output, a value which is not -1 is the + * parent pipe handle corresponding to the pipe which has + * been created. An element of this array is -1 on input + * if and only if it is not -1 on output. + * @param redirectErrorStream redirectErrorStream attribute + * @return the native subprocess HANDLE returned by CreateProcess + */ private static native long create(String cmdstr, String envblock, String dir, - boolean redirectErrorStream, - FileDescriptor in_fd, - FileDescriptor out_fd, - FileDescriptor err_fd) + long[] stdHandles, + boolean redirectErrorStream) throws IOException; private static native boolean closeHandle(long handle); diff -r 6266821dc652 -r 842a7d676774 jdk/src/windows/classes/sun/security/mscapi/SunMSCAPI.java --- a/jdk/src/windows/classes/sun/security/mscapi/SunMSCAPI.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/windows/classes/sun/security/mscapi/SunMSCAPI.java Tue Mar 11 23:37:02 2008 -0700 @@ -48,8 +48,8 @@ private static final String INFO = "Sun's Microsoft Crypto API provider"; static { - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { System.loadLibrary("sunmscapi"); return null; } diff -r 6266821dc652 -r 842a7d676774 jdk/src/windows/native/java/io/FileOutputStream_md.c --- a/jdk/src/windows/native/java/io/FileOutputStream_md.c Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/windows/native/java/io/FileOutputStream_md.c Tue Mar 11 23:37:02 2008 -0700 @@ -39,8 +39,6 @@ jfieldID fos_fd; /* id for jobject 'fd' in java.io.FileOutputStream */ -jfieldID fos_append; - /************************************************************** * static methods to store field ID's in initializers */ @@ -49,7 +47,6 @@ Java_java_io_FileOutputStream_initIDs(JNIEnv *env, jclass fosClass) { fos_fd = (*env)->GetFieldID(env, fosClass, "fd", "Ljava/io/FileDescriptor;"); - fos_append = (*env)->GetFieldID(env, fosClass, "append", "Z"); } /************************************************************** @@ -57,45 +54,20 @@ */ JNIEXPORT void JNICALL -Java_java_io_FileOutputStream_open(JNIEnv *env, jobject this, jstring path) { - fileOpen(env, this, path, fos_fd, O_WRONLY | O_CREAT | O_TRUNC); -} - -JNIEXPORT void JNICALL -Java_java_io_FileOutputStream_openAppend(JNIEnv *env, jobject this, jstring path) { - fileOpen(env, this, path, fos_fd, O_WRONLY | O_CREAT | O_APPEND); +Java_java_io_FileOutputStream_open(JNIEnv *env, jobject this, + jstring path, jboolean append) { + fileOpen(env, this, path, fos_fd, + O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC)); } JNIEXPORT void JNICALL Java_java_io_FileOutputStream_write(JNIEnv *env, jobject this, jint byte) { - jboolean append = (*env)->GetBooleanField(env, this, fos_append); - FD fd = GET_FD(this, fos_fd); - if (fd == -1) { - JNU_ThrowIOException(env, "Stream Closed"); - return; - } - if (append == JNI_TRUE) { - if (IO_Lseek(fd, 0L, SEEK_END) == -1) { - JNU_ThrowIOExceptionWithLastError(env, "Append failed"); - } - } writeSingle(env, this, byte, fos_fd); } JNIEXPORT void JNICALL Java_java_io_FileOutputStream_writeBytes(JNIEnv *env, jobject this, jbyteArray bytes, jint off, jint len) { - jboolean append = (*env)->GetBooleanField(env, this, fos_append); - FD fd = GET_FD(this, fos_fd); - if (fd == -1) { - JNU_ThrowIOException(env, "Stream Closed"); - return; - } - if (append == JNI_TRUE) { - if (IO_Lseek(fd, 0L, SEEK_END) == -1) { - JNU_ThrowIOExceptionWithLastError(env, "Append failed"); - } - } writeBytes(env, this, bytes, off, len, fos_fd); } diff -r 6266821dc652 -r 842a7d676774 jdk/src/windows/native/java/io/io_util_md.c --- a/jdk/src/windows/native/java/io/io_util_md.c Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/windows/native/java/io/io_util_md.c Tue Mar 11 23:37:02 2008 -0700 @@ -42,7 +42,7 @@ extern jboolean onNT = JNI_FALSE; -static int MAX_INPUT_EVENTS = 2000; +static DWORD MAX_INPUT_EVENTS = 2000; void initializeWindowsVersion() { @@ -190,9 +190,16 @@ jlong winFileHandleOpen(JNIEnv *env, jstring path, int flags) { + /* To implement O_APPEND, we use the strategy from + http://msdn2.microsoft.com/en-us/library/aa363858.aspx + "You can get atomic append by opening a file with + FILE_APPEND_DATA access and _without_ FILE_WRITE_DATA access. + If you do this then all writes will ignore the current file + pointer and be done at the end-of file." */ const DWORD access = - (flags & O_RDWR) ? (GENERIC_WRITE | GENERIC_READ) : + (flags & O_APPEND) ? (FILE_GENERIC_WRITE & ~FILE_WRITE_DATA) : (flags & O_WRONLY) ? GENERIC_WRITE : + (flags & O_RDWR) ? (GENERIC_READ | GENERIC_WRITE) : GENERIC_READ; const DWORD sharing = FILE_SHARE_READ | FILE_SHARE_WRITE; @@ -444,24 +451,6 @@ return 0; } -int -handleFileSizeFD(jlong fd, jlong *size) -{ - DWORD sizeLow = 0; - DWORD sizeHigh = 0; - HANDLE h = (HANDLE)fd; - if (h == INVALID_HANDLE_VALUE) { - return -1; - } - sizeLow = GetFileSize(h, &sizeHigh); - if (sizeLow == ((DWORD)-1)) { - if (GetLastError() != ERROR_SUCCESS) { - return -1; - } - } - return (((jlong)sizeHigh) << 32) | sizeLow; -} - JNIEXPORT size_t handleRead(jlong fd, void *buf, jint len) @@ -513,7 +502,7 @@ FD fd = GET_FD(this, fid); HANDLE h = (HANDLE)fd; - if (fd == INVALID_HANDLE_VALUE) { + if (h == INVALID_HANDLE_VALUE) { return 0; } diff -r 6266821dc652 -r 842a7d676774 jdk/src/windows/native/java/io/io_util_md.h --- a/jdk/src/windows/native/java/io/io_util_md.h Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/windows/native/java/io/io_util_md.h Tue Mar 11 23:37:02 2008 -0700 @@ -38,7 +38,6 @@ int handleAvailable(jlong fd, jlong *pbytes); JNIEXPORT int handleSync(jlong fd); int handleSetLength(jlong fd, jlong length); -int handleFileSizeFD(jlong fd, jlong *size); JNIEXPORT size_t handleRead(jlong fd, void *buf, jint len); JNIEXPORT size_t handleWrite(jlong fd, const void *buf, jint len); jint handleClose(JNIEnv *env, jobject this, jfieldID fid); diff -r 6266821dc652 -r 842a7d676774 jdk/src/windows/native/java/lang/ProcessImpl_md.c --- a/jdk/src/windows/native/java/lang/ProcessImpl_md.c Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/windows/native/java/lang/ProcessImpl_md.c Tue Mar 11 23:37:02 2008 -0700 @@ -33,7 +33,12 @@ #include #include -#define PIPE_SIZE 4096 +/* We try to make sure that we can read and write 4095 bytes (the + * fixed limit on Linux) to the pipe on all operating systems without + * deadlock. Windows 2000 inexplicably appears to need an extra 24 + * bytes of slop to avoid deadlock. + */ +#define PIPE_SIZE (4096+24) char * extractExecutablePath(JNIEnv *env, char *source) @@ -120,7 +125,7 @@ static void closeSafely(HANDLE handle) { - if (handle) + if (handle != INVALID_HANDLE_VALUE) CloseHandle(handle); } @@ -129,23 +134,22 @@ jstring cmd, jstring envBlock, jstring dir, - jboolean redirectErrorStream, - jobject in_fd, - jobject out_fd, - jobject err_fd) + jlongArray stdHandles, + jboolean redirectErrorStream) { - HANDLE inRead = 0; - HANDLE inWrite = 0; - HANDLE outRead = 0; - HANDLE outWrite = 0; - HANDLE errRead = 0; - HANDLE errWrite = 0; + HANDLE inRead = INVALID_HANDLE_VALUE; + HANDLE inWrite = INVALID_HANDLE_VALUE; + HANDLE outRead = INVALID_HANDLE_VALUE; + HANDLE outWrite = INVALID_HANDLE_VALUE; + HANDLE errRead = INVALID_HANDLE_VALUE; + HANDLE errWrite = INVALID_HANDLE_VALUE; SECURITY_ATTRIBUTES sa; PROCESS_INFORMATION pi; STARTUPINFO si; LPTSTR pcmd = NULL; LPCTSTR pdir = NULL; LPVOID penvBlock = NULL; + jlong *handles = NULL; jlong ret = 0; OSVERSIONINFO ver; jboolean onNT = JNI_FALSE; @@ -156,17 +160,6 @@ if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) onNT = JNI_TRUE; - sa.nLength = sizeof(sa); - sa.lpSecurityDescriptor = 0; - sa.bInheritHandle = TRUE; - - if (!(CreatePipe(&inRead, &inWrite, &sa, PIPE_SIZE) && - CreatePipe(&outRead, &outWrite, &sa, PIPE_SIZE) && - CreatePipe(&errRead, &errWrite, &sa, PIPE_SIZE))) { - win32Error(env, "CreatePipe"); - goto Catch; - } - assert(cmd != NULL); pcmd = (LPTSTR) JNU_GetStringPlatformChars(env, cmd, NULL); if (pcmd == NULL) goto Catch; @@ -184,19 +177,62 @@ if (penvBlock == NULL) goto Catch; } + assert(stdHandles != NULL); + handles = (*env)->GetLongArrayElements(env, stdHandles, NULL); + if (handles == NULL) goto Catch; + memset(&si, 0, sizeof(si)); si.cb = sizeof(si); si.dwFlags = STARTF_USESTDHANDLES; - si.hStdInput = inRead; - si.hStdOutput = outWrite; - si.hStdError = redirectErrorStream ? outWrite : errWrite; + + sa.nLength = sizeof(sa); + sa.lpSecurityDescriptor = 0; + sa.bInheritHandle = TRUE; + + if (handles[0] != (jlong) -1) { + si.hStdInput = (HANDLE) handles[0]; + handles[0] = (jlong) -1; + } else { + if (! CreatePipe(&inRead, &inWrite, &sa, PIPE_SIZE)) { + win32Error(env, "CreatePipe"); + goto Catch; + } + si.hStdInput = inRead; + SetHandleInformation(inWrite, HANDLE_FLAG_INHERIT, FALSE); + handles[0] = (jlong) inWrite; + } + SetHandleInformation(si.hStdInput, HANDLE_FLAG_INHERIT, TRUE); - SetHandleInformation(inWrite, HANDLE_FLAG_INHERIT, FALSE); - SetHandleInformation(outRead, HANDLE_FLAG_INHERIT, FALSE); - SetHandleInformation(errRead, HANDLE_FLAG_INHERIT, FALSE); + if (handles[1] != (jlong) -1) { + si.hStdOutput = (HANDLE) handles[1]; + handles[1] = (jlong) -1; + } else { + if (! CreatePipe(&outRead, &outWrite, &sa, PIPE_SIZE)) { + win32Error(env, "CreatePipe"); + goto Catch; + } + si.hStdOutput = outWrite; + SetHandleInformation(outRead, HANDLE_FLAG_INHERIT, FALSE); + handles[1] = (jlong) outRead; + } + SetHandleInformation(si.hStdOutput, HANDLE_FLAG_INHERIT, TRUE); - if (redirectErrorStream) - SetHandleInformation(errWrite, HANDLE_FLAG_INHERIT, FALSE); + if (redirectErrorStream) { + si.hStdError = si.hStdOutput; + handles[2] = (jlong) -1; + } else if (handles[2] != (jlong) -1) { + si.hStdError = (HANDLE) handles[2]; + handles[2] = (jlong) -1; + } else { + if (! CreatePipe(&errRead, &errWrite, &sa, PIPE_SIZE)) { + win32Error(env, "CreatePipe"); + goto Catch; + } + si.hStdError = errWrite; + SetHandleInformation(errRead, HANDLE_FLAG_INHERIT, FALSE); + handles[2] = (jlong) errRead; + } + SetHandleInformation(si.hStdError, HANDLE_FLAG_INHERIT, TRUE); if (onNT) processFlag = CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT; @@ -232,9 +268,6 @@ CloseHandle(pi.hThread); ret = (jlong)pi.hProcess; - (*env)->SetLongField(env, in_fd, IO_handle_fdID, (jlong)inWrite); - (*env)->SetLongField(env, out_fd, IO_handle_fdID, (jlong)outRead); - (*env)->SetLongField(env, err_fd, IO_handle_fdID, (jlong)errRead); Finally: /* Always clean up the child's side of the pipes */ @@ -252,6 +285,9 @@ else JNU_ReleaseStringPlatformChars(env, dir, (char *) penvBlock); } + if (handles != NULL) + (*env)->ReleaseLongArrayElements(env, stdHandles, handles, 0); + return ret; Catch: diff -r 6266821dc652 -r 842a7d676774 jdk/src/windows/native/java/lang/java_props_md.c --- a/jdk/src/windows/native/java/lang/java_props_md.c Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/src/windows/native/java/lang/java_props_md.c Tue Mar 11 23:37:02 2008 -0700 @@ -673,13 +673,13 @@ /* OS properties */ { char buf[100]; - OSVERSIONINFO ver; + OSVERSIONINFOEX ver; ver.dwOSVersionInfoSize = sizeof(ver); - GetVersionEx(&ver); + GetVersionEx((OSVERSIONINFO *) &ver); /* * From msdn page on OSVERSIONINFOEX, current as of this - * writing decoding of dwMajorVersion and dwMinorVersion. + * writing, decoding of dwMajorVersion and dwMinorVersion. * * Operating system dwMajorVersion dwMinorVersion * ================== ============== ============== @@ -692,7 +692,7 @@ * Windows 2000 5 0 * Windows XP 5 1 * Windows Server 2003 family 5 2 - * Windows Vista 6 0 + * Windows Vista family 6 0 * * This mapping will presumably be augmented as new Windows * versions are released. @@ -724,7 +724,20 @@ default: sprops.os_name = "Windows NT (unknown)"; break; } } else if (ver.dwMajorVersion == 6) { - sprops.os_name = "Windows Vista"; + /* + * From MSDN OSVERSIONINFOEX documentation: + * + * "Because the version numbers for Windows Server 2008 + * and Windows Vista are identical, you must also test + * whether the wProductType member is VER_NT_WORKSTATION. + * If wProductType is VER_NT_WORKSTATION, the operating + * system is Windows Vista; otherwise, it is Windows + * Server 2008." + */ + if (ver.wProductType == VER_NT_WORKSTATION) + sprops.os_name = "Windows Vista"; + else + sprops.os_name = "Windows Server 2008"; } else { sprops.os_name = "Windows NT (unknown)"; } diff -r 6266821dc652 -r 842a7d676774 jdk/test/java/io/FileOutputStream/AtomicAppend.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/io/FileOutputStream/AtomicAppend.java Tue Mar 11 23:37:02 2008 -0700 @@ -0,0 +1,81 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6631352 + * @summary Check that appends are atomic + */ + +import java.io.File; +import java.io.FileOutputStream; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; + +public class AtomicAppend { + // Before the fix for + // 6631352: Implement atomic append mode using FILE_APPEND_DATA (win) + // this would fail intermittently on windows + void test(String[] args) throws Throwable { + final int nThreads = 10; + final int writes = 1000; + final File file = new File("foo"); + file.delete(); + try { + final ExecutorService es = Executors.newFixedThreadPool(nThreads); + for (int i = 0; i < nThreads; i++) + es.execute(new Runnable() { public void run() { + try { + FileOutputStream s = new FileOutputStream(file, true); + for (int j = 0; j < 1000; j++) { + s.write((int) 'x'); + s.flush(); + } + s.close(); + } catch (Throwable t) { unexpected(t); }}}); + es.shutdown(); + es.awaitTermination(10L, TimeUnit.MINUTES); + equal(file.length(), (long) (nThreads * writes)); + } finally { + file.delete(); + } + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new AtomicAppend().instanceMain(args);} + void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} diff -r 6266821dc652 -r 842a7d676774 jdk/test/java/lang/ProcessBuilder/Basic.java --- a/jdk/test/java/lang/ProcessBuilder/Basic.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/test/java/lang/ProcessBuilder/Basic.java Tue Mar 11 23:37:02 2008 -0700 @@ -25,12 +25,15 @@ * @test * @bug 4199068 4738465 4937983 4930681 4926230 4931433 4932663 4986689 * 5026830 5023243 5070673 4052517 4811767 6192449 6397034 6413313 - * 6464154 6523983 6206031 + * 6464154 6523983 6206031 4960438 6631352 6631966 * @summary Basic tests for Process and Environment Variable code * @run main/othervm Basic * @author Martin Buchholz */ +import java.lang.ProcessBuilder.Redirect; +import static java.lang.ProcessBuilder.Redirect.*; + import java.io.*; import java.util.*; import java.security.*; @@ -257,7 +260,29 @@ public static class JavaChild { public static void main(String args[]) throws Throwable { String action = args[0]; - if (action.equals("System.getenv(String)")) { + if (action.equals("testIO")) { + String expected = "standard input"; + char[] buf = new char[expected.length()+1]; + int n = new InputStreamReader(System.in).read(buf,0,buf.length); + if (n != expected.length()) + System.exit(5); + if (! new String(buf,0,n).equals(expected)) + System.exit(5); + System.err.print("standard error"); + System.out.print("standard output"); + } else if (action.equals("testInheritIO")) { + List childArgs = new ArrayList(javaChildArgs); + childArgs.add("testIO"); + ProcessBuilder pb = new ProcessBuilder(childArgs); + pb.inheritIO(); + ProcessResults r = run(pb); + if (! r.out().equals("")) + System.exit(7); + if (! r.err().equals("")) + System.exit(8); + if (r.exitValue() != 0) + System.exit(9); + } else if (action.equals("System.getenv(String)")) { String val = System.getenv(args[1]); printUTF8(val == null ? "null" : val); } else if (action.equals("System.getenv(\\u1234)")) { @@ -599,6 +624,333 @@ } catch (Throwable t) { unexpected(t); } } + static void checkRedirects(ProcessBuilder pb, + Redirect in, Redirect out, Redirect err) { + equal(pb.redirectInput(), in); + equal(pb.redirectOutput(), out); + equal(pb.redirectError(), err); + } + + static void redirectIO(ProcessBuilder pb, + Redirect in, Redirect out, Redirect err) { + pb.redirectInput(in); + pb.redirectOutput(out); + pb.redirectError(err); + } + + static void setFileContents(File file, String contents) { + try { + Writer w = new FileWriter(file); + w.write(contents); + w.close(); + } catch (Throwable t) { unexpected(t); } + } + + static String fileContents(File file) { + try { + Reader r = new FileReader(file); + StringBuilder sb = new StringBuilder(); + char[] buffer = new char[1024]; + int n; + while ((n = r.read(buffer)) != -1) + sb.append(buffer,0,n); + r.close(); + return new String(sb); + } catch (Throwable t) { unexpected(t); return ""; } + } + + static void testIORedirection() throws Throwable { + final File ifile = new File("ifile"); + final File ofile = new File("ofile"); + final File efile = new File("efile"); + ifile.delete(); + ofile.delete(); + efile.delete(); + + //---------------------------------------------------------------- + // Check mutual inequality of different types of Redirect + //---------------------------------------------------------------- + Redirect[] redirects = + { PIPE, + INHERIT, + Redirect.from(ifile), + Redirect.to(ifile), + Redirect.appendTo(ifile), + Redirect.from(ofile), + Redirect.to(ofile), + Redirect.appendTo(ofile), + }; + for (int i = 0; i < redirects.length; i++) + for (int j = 0; j < redirects.length; j++) + equal(redirects[i].equals(redirects[j]), (i == j)); + + //---------------------------------------------------------------- + // Check basic properties of different types of Redirect + //---------------------------------------------------------------- + equal(PIPE.type(), Redirect.Type.PIPE); + equal(PIPE.toString(), "PIPE"); + equal(PIPE.file(), null); + + equal(INHERIT.type(), Redirect.Type.INHERIT); + equal(INHERIT.toString(), "INHERIT"); + equal(INHERIT.file(), null); + + equal(Redirect.from(ifile).type(), Redirect.Type.READ); + equal(Redirect.from(ifile).toString(), + "redirect to read from file \"ifile\""); + equal(Redirect.from(ifile).file(), ifile); + equal(Redirect.from(ifile), + Redirect.from(ifile)); + equal(Redirect.from(ifile).hashCode(), + Redirect.from(ifile).hashCode()); + + equal(Redirect.to(ofile).type(), Redirect.Type.WRITE); + equal(Redirect.to(ofile).toString(), + "redirect to write to file \"ofile\""); + equal(Redirect.to(ofile).file(), ofile); + equal(Redirect.to(ofile), + Redirect.to(ofile)); + equal(Redirect.to(ofile).hashCode(), + Redirect.to(ofile).hashCode()); + + equal(Redirect.appendTo(ofile).type(), Redirect.Type.APPEND); + equal(Redirect.appendTo(efile).toString(), + "redirect to append to file \"efile\""); + equal(Redirect.appendTo(efile).file(), efile); + equal(Redirect.appendTo(efile), + Redirect.appendTo(efile)); + equal(Redirect.appendTo(efile).hashCode(), + Redirect.appendTo(efile).hashCode()); + + //---------------------------------------------------------------- + // Check initial values of redirects + //---------------------------------------------------------------- + List childArgs = new ArrayList(javaChildArgs); + childArgs.add("testIO"); + final ProcessBuilder pb = new ProcessBuilder(childArgs); + checkRedirects(pb, PIPE, PIPE, PIPE); + + //---------------------------------------------------------------- + // Check inheritIO + //---------------------------------------------------------------- + pb.inheritIO(); + checkRedirects(pb, INHERIT, INHERIT, INHERIT); + + //---------------------------------------------------------------- + // Check setters and getters agree + //---------------------------------------------------------------- + pb.redirectInput(ifile); + equal(pb.redirectInput().file(), ifile); + equal(pb.redirectInput(), Redirect.from(ifile)); + + pb.redirectOutput(ofile); + equal(pb.redirectOutput().file(), ofile); + equal(pb.redirectOutput(), Redirect.to(ofile)); + + pb.redirectError(efile); + equal(pb.redirectError().file(), efile); + equal(pb.redirectError(), Redirect.to(efile)); + + THROWS(IllegalArgumentException.class, + new Fun(){void f() { + pb.redirectInput(Redirect.to(ofile)); }}, + new Fun(){void f() { + pb.redirectInput(Redirect.appendTo(ofile)); }}, + new Fun(){void f() { + pb.redirectOutput(Redirect.from(ifile)); }}, + new Fun(){void f() { + pb.redirectError(Redirect.from(ifile)); }}); + + THROWS(IOException.class, + // Input file does not exist + new Fun(){void f() throws Throwable { pb.start(); }}); + setFileContents(ifile, "standard input"); + + //---------------------------------------------------------------- + // Writing to non-existent files + //---------------------------------------------------------------- + { + ProcessResults r = run(pb); + equal(r.exitValue(), 0); + equal(fileContents(ofile), "standard output"); + equal(fileContents(efile), "standard error"); + equal(r.out(), ""); + equal(r.err(), ""); + ofile.delete(); + efile.delete(); + } + + //---------------------------------------------------------------- + // Both redirectErrorStream + redirectError + //---------------------------------------------------------------- + { + pb.redirectErrorStream(true); + ProcessResults r = run(pb); + equal(r.exitValue(), 0); + equal(fileContents(ofile), + "standard error" + "standard output"); + equal(fileContents(efile), ""); + equal(r.out(), ""); + equal(r.err(), ""); + ofile.delete(); + efile.delete(); + } + + //---------------------------------------------------------------- + // Appending to existing files + //---------------------------------------------------------------- + { + setFileContents(ofile, "ofile-contents"); + setFileContents(efile, "efile-contents"); + pb.redirectOutput(Redirect.appendTo(ofile)); + pb.redirectError(Redirect.appendTo(efile)); + pb.redirectErrorStream(false); + ProcessResults r = run(pb); + equal(r.exitValue(), 0); + equal(fileContents(ofile), + "ofile-contents" + "standard output"); + equal(fileContents(efile), + "efile-contents" + "standard error"); + equal(r.out(), ""); + equal(r.err(), ""); + ofile.delete(); + efile.delete(); + } + + //---------------------------------------------------------------- + // Replacing existing files + //---------------------------------------------------------------- + { + setFileContents(ofile, "ofile-contents"); + setFileContents(efile, "efile-contents"); + pb.redirectOutput(ofile); + pb.redirectError(Redirect.to(efile)); + ProcessResults r = run(pb); + equal(r.exitValue(), 0); + equal(fileContents(ofile), "standard output"); + equal(fileContents(efile), "standard error"); + equal(r.out(), ""); + equal(r.err(), ""); + ofile.delete(); + efile.delete(); + } + + //---------------------------------------------------------------- + // Appending twice to the same file? + //---------------------------------------------------------------- + { + setFileContents(ofile, "ofile-contents"); + setFileContents(efile, "efile-contents"); + Redirect appender = Redirect.appendTo(ofile); + pb.redirectOutput(appender); + pb.redirectError(appender); + ProcessResults r = run(pb); + equal(r.exitValue(), 0); + equal(fileContents(ofile), + "ofile-contents" + + "standard error" + + "standard output"); + equal(fileContents(efile), "efile-contents"); + equal(r.out(), ""); + equal(r.err(), ""); + ifile.delete(); + ofile.delete(); + efile.delete(); + } + + //---------------------------------------------------------------- + // Testing INHERIT is harder. + // Note that this requires __FOUR__ nested JVMs involved in one test, + // if you count the harness JVM. + //---------------------------------------------------------------- + { + redirectIO(pb, PIPE, PIPE, PIPE); + List command = pb.command(); + command.set(command.size() - 1, "testInheritIO"); + Process p = pb.start(); + new PrintStream(p.getOutputStream()).print("standard input"); + p.getOutputStream().close(); + ProcessResults r = run(p); + equal(r.exitValue(), 0); + equal(r.out(), "standard output"); + equal(r.err(), "standard error"); + } + + //---------------------------------------------------------------- + // Test security implications of I/O redirection + //---------------------------------------------------------------- + + // Read access to current directory is always granted; + // So create a tmpfile for input instead. + final File tmpFile = File.createTempFile("Basic", "tmp"); + setFileContents(tmpFile, "standard input"); + + final Policy policy = new Policy(); + Policy.setPolicy(policy); + System.setSecurityManager(new SecurityManager()); + try { + final Permission xPermission + = new FilePermission("<>", "execute"); + final Permission rxPermission + = new FilePermission("<>", "read,execute"); + final Permission wxPermission + = new FilePermission("<>", "write,execute"); + final Permission rwxPermission + = new FilePermission("<>", "read,write,execute"); + + THROWS(SecurityException.class, + new Fun() { void f() throws IOException { + policy.setPermissions(xPermission); + redirectIO(pb, from(tmpFile), PIPE, PIPE); + pb.start();}}, + new Fun() { void f() throws IOException { + policy.setPermissions(rxPermission); + redirectIO(pb, PIPE, to(ofile), PIPE); + pb.start();}}, + new Fun() { void f() throws IOException { + policy.setPermissions(rxPermission); + redirectIO(pb, PIPE, PIPE, to(efile)); + pb.start();}}); + + { + policy.setPermissions(rxPermission); + redirectIO(pb, from(tmpFile), PIPE, PIPE); + ProcessResults r = run(pb); + equal(r.out(), "standard output"); + equal(r.err(), "standard error"); + } + + { + policy.setPermissions(wxPermission); + redirectIO(pb, PIPE, to(ofile), to(efile)); + Process p = pb.start(); + new PrintStream(p.getOutputStream()).print("standard input"); + p.getOutputStream().close(); + ProcessResults r = run(p); + policy.setPermissions(rwxPermission); + equal(fileContents(ofile), "standard output"); + equal(fileContents(efile), "standard error"); + } + + { + policy.setPermissions(rwxPermission); + redirectIO(pb, from(tmpFile), to(ofile), to(efile)); + ProcessResults r = run(pb); + policy.setPermissions(rwxPermission); + equal(fileContents(ofile), "standard output"); + equal(fileContents(efile), "standard error"); + } + + } finally { + policy.setPermissions(new RuntimePermission("setSecurityManager")); + System.setSecurityManager(null); + tmpFile.delete(); + ifile.delete(); + ofile.delete(); + efile.delete(); + } + } + private static void realMain(String[] args) throws Throwable { if (Windows.is()) System.out.println("This appears to be a Windows system."); @@ -607,6 +959,9 @@ if (UnicodeOS.is()) System.out.println("This appears to be a Unicode-based OS."); + try { testIORedirection(); } + catch (Throwable t) { unexpected(t); } + //---------------------------------------------------------------- // Basic tests for setting, replacing and deleting envvars //---------------------------------------------------------------- @@ -1354,7 +1709,8 @@ execPermission); ProcessBuilder pb = new ProcessBuilder("env"); pb.environment().put("foo","bar"); - pb.start(); + Process p = pb.start(); + closeStreams(p); } catch (IOException e) { // OK } catch (Throwable t) { unexpected(t); } @@ -1378,6 +1734,14 @@ } + static void closeStreams(Process p) { + try { + p.getOutputStream().close(); + p.getInputStream().close(); + p.getErrorStream().close(); + } catch (Throwable t) { unexpected(t); } + } + //---------------------------------------------------------------- // A Policy class designed to make permissions fiddling very easy. //---------------------------------------------------------------- @@ -1432,10 +1796,19 @@ } } catch (Throwable t) { throwable = t; + } finally { + try { is.close(); } + catch (Throwable t) { throwable = t; } } } } + static ProcessResults run(ProcessBuilder pb) { + try { + return run(pb.start()); + } catch (Throwable t) { unexpected(t); return null; } + } + private static ProcessResults run(Process p) { Throwable throwable = null; int exitValue = -1; diff -r 6266821dc652 -r 842a7d676774 jdk/test/java/nio/channels/Channels/ShortWrite.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/nio/channels/Channels/ShortWrite.java Tue Mar 11 23:37:02 2008 -0700 @@ -0,0 +1,83 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 6448457 + * @summary Test Channels.newOutputStream returns OutputStream that handles + * short writes from the underlying channel + */ + +import java.io.OutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.*; +import java.util.Random; + +public class ShortWrite { + + static Random rand = new Random(); + static int bytesWritten = 0; + + public static void main(String[] args) throws IOException { + + WritableByteChannel wbc = new WritableByteChannel() { + public int write(ByteBuffer src) { + int rem = src.remaining(); + if (rem > 0) { + // short write + int n = rand.nextInt(rem) + 1; + src.position(src.position() + n); + bytesWritten += n; + return n; + } else { + return 0; + } + } + public void close() throws IOException { + throw new RuntimeException("not implemented"); + } + public boolean isOpen() { + throw new RuntimeException("not implemented"); + } + }; + + // wrap Channel with OutputStream + OutputStream out = Channels.newOutputStream(wbc); + + + // write 100, 99, 98, ... 1 + // and check that the expected number of bytes is written + int expected = 0; + byte[] buf = new byte[100]; + for (int i=0; i maps) { + Map first = maps.get(0); + for (Map map : maps) + mapsEqual(first, map); + } + + void put(List maps, Object key, Object val) { + for (Map map : maps) + map.put(key, val); + mapsEqual(maps); + } + + void removeLastTwo(List maps) { + Map first = maps.get(0); + int size = first.size(); + Iterator fit = first.keySet().iterator(); + for (int j = 0; j < size - 2; j++) + fit.next(); + Object x1 = fit.next(); + Object x2 = fit.next(); + + for (Map map : maps) { + Iterator it = map.keySet().iterator(); + while (it.hasNext()) { + Object x = it.next(); + if (x == x1 || x == x2) + it.remove(); + } + } + mapsEqual(maps); + } + + void remove(Map m, Iterator it) { + int size = m.size(); + it.remove(); + if (m.size() != size-1) + throw new Error(String.format("Incorrect size!%nmap=%s, size=%d%n", + m.toString(), m.size())); + } + + void test(String[] args) throws Throwable { + final int iterations = 100; + final Random r = new Random(); + + for (int i = 0; i < iterations; i++) { + List maps = Arrays.asList( + new Map[] { + new IdentityHashMap(11), + new HashMap(16), + new LinkedHashMap(16), + new WeakHashMap(16), + new Hashtable(16), + new TreeMap(), + new ConcurrentHashMap(16), + new ConcurrentSkipListMap() }); + + for (int j = 0; j < 10; j++) + put(maps, r.nextInt(100), r.nextInt(100)); + removeLastTwo(maps); + } + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new LockStep().instanceMain(args);} + void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} diff -r 6266821dc652 -r 842a7d676774 jdk/test/java/util/concurrent/DelayQueue/Stress.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/util/concurrent/DelayQueue/Stress.java Tue Mar 11 23:37:02 2008 -0700 @@ -0,0 +1,61 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.util.concurrent.*; +import static java.util.concurrent.TimeUnit.*; + +/** + * This is not a regression test, but a stress benchmark test for + * 6609775: Reduce context switches in DelayQueue due to signalAll + * + * This runs in the same wall clock time, but much reduced cpu time, + * with the changes for 6609775. + */ +public class Stress { + + public static void main(String[] args) throws Throwable { + + final DelayQueue q = new DelayQueue(); + final long t0 = System.nanoTime(); + for (long i = 0; i < 1000; i++) { + final long expiry = t0 + i*10L*1000L*1000L; + q.add(new Delayed() { + public long getDelay(TimeUnit unit) { + return unit.convert(expiry - System.nanoTime(), + NANOSECONDS); + } + public int compareTo(Delayed x) { + long d = getDelay(NANOSECONDS) + - x.getDelay(NANOSECONDS); + return d < 0 ? -1 : d > 0 ? 1 : 0; }}); + } + + for (int i = 0; i < 300; i++) + new Thread() { public void run() { + try { + while (!q.isEmpty()) + q.poll(10L, TimeUnit.SECONDS); + } catch (Throwable t) { t.printStackTrace(); } + }}.start(); + } +} diff -r 6266821dc652 -r 842a7d676774 jdk/test/java/util/concurrent/LinkedBlockingQueue/OfferRemoveLoops.java --- a/jdk/test/java/util/concurrent/LinkedBlockingQueue/OfferRemoveLoops.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/test/java/util/concurrent/LinkedBlockingQueue/OfferRemoveLoops.java Tue Mar 11 23:37:02 2008 -0700 @@ -23,7 +23,7 @@ /* * @test - * @bug 6316155 + * @bug 6316155 6595669 * @summary Test concurrent offer vs. remove * @author Martin Buchholz */ @@ -50,15 +50,18 @@ private static void testQueue(final BlockingQueue q) throws Throwable { System.out.println(q.getClass()); final int count = 10000; + final long quittingTime = System.nanoTime() + 1L * 1000L * 1000L * 1000L; Thread t1 = new ControlledThread() { protected void realRun() { for (int i = 0, j = 0; i < count; i++) - while (! q.remove(String.valueOf(i))) + while (! q.remove(String.valueOf(i)) + && System.nanoTime() - quittingTime < 0) Thread.yield();}}; Thread t2 = new ControlledThread() { protected void realRun() { for (int i = 0, j = 0; i < count; i++) - while (! q.offer(String.valueOf(i))) + while (! q.offer(String.valueOf(i)) + && System.nanoTime() - quittingTime < 0) Thread.yield();}}; t1.setDaemon(true); t2.setDaemon(true); t1.start(); t2.start(); diff -r 6266821dc652 -r 842a7d676774 jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/BasicCancelTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/BasicCancelTest.java Tue Mar 11 23:37:02 2008 -0700 @@ -0,0 +1,113 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6602600 + * @run main/othervm -Xmx8m BasicCancelTest + * @summary Check effectiveness of RemoveOnCancelPolicy + */ + +import java.util.concurrent.*; +import java.util.Random; + +/** + * Simple timer cancellation test. Submits tasks to a scheduled executor + * service and immediately cancels them. + */ +public class BasicCancelTest { + + void checkShutdown(final ExecutorService es) { + final Runnable nop = new Runnable() {public void run() {}}; + try { + if (new Random().nextBoolean()) { + check(es.isShutdown()); + if (es instanceof ThreadPoolExecutor) + check(((ThreadPoolExecutor) es).isTerminating() + || es.isTerminated()); + THROWS(RejectedExecutionException.class, + new F(){void f(){es.execute(nop);}}); + } + } catch (Throwable t) { unexpected(t); } + } + + void checkTerminated(final ThreadPoolExecutor tpe) { + try { + checkShutdown(tpe); + check(tpe.getQueue().isEmpty()); + check(tpe.isTerminated()); + check(! tpe.isTerminating()); + equal(tpe.getActiveCount(), 0); + equal(tpe.getPoolSize(), 0); + equal(tpe.getTaskCount(), tpe.getCompletedTaskCount()); + check(tpe.awaitTermination(0, TimeUnit.SECONDS)); + } catch (Throwable t) { unexpected(t); } + } + + void test(String[] args) throws Throwable { + + final ScheduledThreadPoolExecutor pool = + new ScheduledThreadPoolExecutor(1); + + // Needed to avoid OOME + pool.setRemoveOnCancelPolicy(true); + + final long moreThanYouCanChew = Runtime.getRuntime().freeMemory() / 4; + System.out.printf("moreThanYouCanChew=%d%n", moreThanYouCanChew); + + Runnable noopTask = new Runnable() { public void run() {}}; + + for (long i = 0; i < moreThanYouCanChew; i++) + pool.schedule(noopTask, 10, TimeUnit.MINUTES).cancel(true); + + pool.shutdown(); + check(pool.awaitTermination(1L, TimeUnit.DAYS)); + checkTerminated(pool); + equal(pool.getTaskCount(), 0L); + equal(pool.getCompletedTaskCount(), 0L); + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new BasicCancelTest().instanceMain(args);} + void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} + abstract class F {abstract void f() throws Throwable;} + void THROWS(Class k, F... fs) { + for (F f : fs) + try {f.f(); fail("Expected " + k.getName() + " not thrown");} + catch (Throwable t) { + if (k.isAssignableFrom(t.getClass())) pass(); + else unexpected(t);}} +} diff -r 6266821dc652 -r 842a7d676774 jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/Stress.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/Stress.java Tue Mar 11 23:37:02 2008 -0700 @@ -0,0 +1,54 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.util.concurrent.*; + +/** + * This is not a regression test, but a stress benchmark test for + * 6602600: Fast removal of cancelled scheduled thread pool tasks + * + * This runs in the same wall clock time, but much reduced cpu time, + * with the changes for 6602600. + */ +public class Stress { + + public static void main(String[] args) throws Throwable { + + final CountDownLatch count = new CountDownLatch(1000); + + final ScheduledThreadPoolExecutor pool = + new ScheduledThreadPoolExecutor(100); + pool.prestartAllCoreThreads(); + + final Runnable incTask = new Runnable() { public void run() { + count.countDown(); + }}; + + pool.scheduleAtFixedRate(incTask, 0, 10, TimeUnit.MILLISECONDS); + + count.await(); + + pool.shutdown(); + pool.awaitTermination(1L, TimeUnit.DAYS); + } +} diff -r 6266821dc652 -r 842a7d676774 jdk/test/java/util/concurrent/SynchronousQueue/Fairness.java --- a/jdk/test/java/util/concurrent/SynchronousQueue/Fairness.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/test/java/util/concurrent/SynchronousQueue/Fairness.java Tue Mar 11 23:37:02 2008 -0700 @@ -23,36 +23,49 @@ /* * @test - * @bug 4992438 - * @compile -source 1.5 Fairness.java - * @run main Fairness + * @bug 4992438 6633113 * @summary Checks that fairness setting is respected. */ import java.util.concurrent.*; +import java.util.concurrent.locks.*; public class Fairness { private static void testFairness(boolean fair, final BlockingQueue q) - throws Exception + throws Throwable { - for (int i = 0; i < 3; i++) { - final Integer I = new Integer(i); - new Thread() { public void run() { - try { q.put(I); } catch (Exception e) {} - }}.start(); - Thread.currentThread().sleep(100); + final ReentrantLock lock = new ReentrantLock(); + final Condition ready = lock.newCondition(); + final int threadCount = 10; + final Throwable[] badness = new Throwable[1]; + lock.lock(); + for (int i = 0; i < threadCount; i++) { + final Integer I = i; + Thread t = new Thread() { public void run() { + try { + lock.lock(); + ready.signal(); + lock.unlock(); + q.put(I); + } catch (Throwable t) { badness[0] = t; }}}; + t.start(); + ready.await(); + // Probably unnecessary, but should be bullet-proof + while (t.getState() == Thread.State.RUNNABLE) + Thread.yield(); } - for (int i = 0; i < 3; i++) { - int j = q.take().intValue(); - System.err.printf("%d%n",j); + for (int i = 0; i < threadCount; i++) { + int j = q.take(); // Non-fair queues are lifo in our implementation - if (fair ? j != i : j != 2-i) - throw new Exception("No fair!"); + if (fair ? j != i : j != threadCount - 1 - i) + throw new Error(String.format("fair=%b i=%d j=%d%n", + fair, i, j)); } + if (badness[0] != null) throw new Error(badness[0]); } - public static void main(String[] args) throws Exception { + public static void main(String[] args) throws Throwable { testFairness(false, new SynchronousQueue()); testFairness(false, new SynchronousQueue(false)); testFairness(true, new SynchronousQueue(true)); diff -r 6266821dc652 -r 842a7d676774 jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/Count.java --- a/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/Count.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/Count.java Tue Mar 11 23:37:02 2008 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-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 @@ -23,21 +23,89 @@ /* * @test - * @bug 6207928 6328220 6378321 + * @bug 6207928 6328220 6378321 6625723 * @summary Recursive lock invariant sanity checks * @author Martin Buchholz */ +import java.io.*; import java.util.*; import java.util.concurrent.*; import java.util.concurrent.locks.*; // I am the Cownt, and I lahve to cownt. public class Count { - private static void realMain(String[] args) throws Throwable { - final ReentrantLock rl = new ReentrantLock(); - final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); + final Random rnd = new Random(); + + void lock(Lock lock) { + try { + switch (rnd.nextInt(4)) { + case 0: lock.lock(); break; + case 1: lock.lockInterruptibly(); break; + case 2: check(lock.tryLock()); break; + case 3: check(lock.tryLock(45, TimeUnit.MINUTES)); break; + } + } catch (Throwable t) { unexpected(t); } + } + + void test(String[] args) throws Throwable { + for (boolean fair : new boolean[] { true, false }) + for (boolean serialClone : new boolean[] { true, false }) { + testReentrantLocks(fair, serialClone); + testConcurrentReadLocks(fair, serialClone); + } + } + + void testConcurrentReadLocks(final boolean fair, + final boolean serialClone) throws Throwable { + final int nThreads = 10; + final CyclicBarrier barrier = new CyclicBarrier(nThreads); + final ExecutorService es = Executors.newFixedThreadPool(nThreads); + final ReentrantReadWriteLock rwl = serialClone ? + serialClone(new ReentrantReadWriteLock(fair)) : + new ReentrantReadWriteLock(fair); + for (int i = 0; i < nThreads; i++) { + es.submit(new Runnable() { public void run() { + try { + int n = 5; + for (int i = 0; i < n; i++) { + barrier.await(); + equal(rwl.getReadHoldCount(), i); + equal(rwl.getWriteHoldCount(), 0); + check(! rwl.isWriteLocked()); + equal(rwl.getReadLockCount(), nThreads * i); + barrier.await(); + lock(rwl.readLock()); + } + for (int i = 0; i < n; i++) { + rwl.readLock().unlock(); + barrier.await(); + equal(rwl.getReadHoldCount(), n-i-1); + equal(rwl.getReadLockCount(), nThreads*(n-i-1)); + equal(rwl.getWriteHoldCount(), 0); + check(! rwl.isWriteLocked()); + barrier.await(); + } + THROWS(IllegalMonitorStateException.class, + new F(){void f(){rwl.readLock().unlock();}}, + new F(){void f(){rwl.writeLock().unlock();}}); + barrier.await(); + } catch (Throwable t) { unexpected(t); }}});} + es.shutdown(); + check(es.awaitTermination(10, TimeUnit.SECONDS)); + } + + void testReentrantLocks(final boolean fair, + final boolean serialClone) throws Throwable { + final ReentrantLock rl = serialClone ? + serialClone(new ReentrantLock(fair)) : + new ReentrantLock(fair); + final ReentrantReadWriteLock rwl = serialClone ? + serialClone(new ReentrantReadWriteLock(fair)) : + new ReentrantReadWriteLock(fair); final int depth = 10; + equal(rl.isFair(), fair); + equal(rwl.isFair(), fair); check(! rl.isLocked()); check(! rwl.isWriteLocked()); check(! rl.isHeldByCurrentThread()); @@ -50,28 +118,11 @@ equal(rwl.getReadHoldCount(), i); equal(rwl.getWriteHoldCount(), i); equal(rwl.writeLock().getHoldCount(), i); - switch (i%4) { - case 0: - rl.lock(); - rwl.writeLock().lock(); - rwl.readLock().lock(); - break; - case 1: - rl.lockInterruptibly(); - rwl.writeLock().lockInterruptibly(); - rwl.readLock().lockInterruptibly(); - break; - case 2: - check(rl.tryLock()); - check(rwl.writeLock().tryLock()); - check(rwl.readLock().tryLock()); - break; - case 3: - check(rl.tryLock(454, TimeUnit.MILLISECONDS)); - check(rwl.writeLock().tryLock(454, TimeUnit.NANOSECONDS)); - check(rwl.readLock().tryLock(454, TimeUnit.HOURS)); - break; - } + equal(rl.isLocked(), i > 0); + equal(rwl.isWriteLocked(), i > 0); + lock(rl); + lock(rwl.writeLock()); + lock(rwl.readLock()); } for (int i = depth; i > 0; i--) { @@ -95,20 +146,48 @@ rwl.writeLock().unlock(); rl.unlock(); } + THROWS(IllegalMonitorStateException.class, + new F(){void f(){rl.unlock();}}, + new F(){void f(){rwl.readLock().unlock();}}, + new F(){void f(){rwl.writeLock().unlock();}}); } //--------------------- Infrastructure --------------------------- - static volatile int passed = 0, failed = 0; - static void pass() {passed++;} - static void fail() {failed++; Thread.dumpStack();} - static void fail(String msg) {System.out.println(msg); fail();} - static void unexpected(Throwable t) {failed++; t.printStackTrace();} - static void check(boolean cond) {if (cond) pass(); else fail();} - static void equal(Object x, Object y) { + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { if (x == null ? y == null : x.equals(y)) pass(); else fail(x + " not equal to " + y);} public static void main(String[] args) throws Throwable { - try {realMain(args);} catch (Throwable t) {unexpected(t);} + new Count().instanceMain(args);} + void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); if (failed > 0) throw new AssertionError("Some tests failed");} + abstract class F {abstract void f() throws Throwable;} + void THROWS(Class k, F... fs) { + for (F f : fs) + try {f.f(); fail("Expected " + k.getName() + " not thrown");} + catch (Throwable t) { + if (k.isAssignableFrom(t.getClass())) pass(); + else unexpected(t);}} + + static byte[] serializedForm(Object obj) { + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + new ObjectOutputStream(baos).writeObject(obj); + return baos.toByteArray(); + } catch (IOException e) { throw new RuntimeException(e); }} + static Object readObject(byte[] bytes) + throws IOException, ClassNotFoundException { + InputStream is = new ByteArrayInputStream(bytes); + return new ObjectInputStream(is).readObject();} + @SuppressWarnings("unchecked") + static T serialClone(T obj) { + try { return (T) readObject(serializedForm(obj)); } + catch (Exception e) { throw new RuntimeException(e); }} } diff -r 6266821dc652 -r 842a7d676774 jdk/test/javax/management/mxbean/JMXServiceURLTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/management/mxbean/JMXServiceURLTest.java Tue Mar 11 23:37:02 2008 -0700 @@ -0,0 +1,103 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test JMXServiceURLTest + * @bug 6607114 6670375 + * @summary Test that JMXServiceURL works correctly in MXBeans + * @author Eamonn McManus + */ + +import java.lang.management.ManagementFactory; +import javax.management.JMX; +import javax.management.MBeanServer; +import javax.management.ObjectName; +import javax.management.openmbean.CompositeData; +import javax.management.openmbean.CompositeType; +import javax.management.openmbean.OpenType; +import javax.management.openmbean.SimpleType; +import javax.management.remote.JMXServiceURL; + +public class JMXServiceURLTest { + public static interface UrlMXBean { + public JMXServiceURL getUrl(); + public void setUrl(JMXServiceURL url); + } + + public static class UrlImpl implements UrlMXBean { + volatile JMXServiceURL url; + + public JMXServiceURL getUrl() { + return url; + } + + public void setUrl(JMXServiceURL url) { + this.url = url; + } + } + + public static void main(String[] args) throws Exception { + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + ObjectName name = new ObjectName("a:b=c"); + UrlImpl urlImpl = new UrlImpl(); + mbs.registerMBean(urlImpl, name); + + JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://host:8000/noddy"); + UrlMXBean proxy = JMX.newMXBeanProxy(mbs, name, UrlMXBean.class); + proxy.setUrl(url); + assertEquals(url, urlImpl.url); + JMXServiceURL url2 = proxy.getUrl(); + assertEquals(url, url2); + + CompositeData cd = (CompositeData) mbs.getAttribute(name, "Url"); + CompositeType ct = cd.getCompositeType(); + // Make sure it looks like what we expect. This will have to be + // changed if ever we add new properties to CompositeType. In that + // case this test should also check interoperability between the + // current version and the new version. + assertEquals(4, ct.keySet().size()); + Object[][] expectedItems = { + {"protocol", SimpleType.STRING, "rmi"}, + {"host", SimpleType.STRING, "host"}, + {"port", SimpleType.INTEGER, 8000}, + {"URLPath", SimpleType.STRING, "/noddy"}, + }; + for (Object[] expectedItem : expectedItems) { + String itemName = (String) expectedItem[0]; + OpenType expectedType = (OpenType) expectedItem[1]; + Object expectedValue = expectedItem[2]; + OpenType actualType = ct.getType(itemName); + assertEquals(expectedType, actualType); + Object actualValue = cd.get(itemName); + assertEquals(expectedValue, actualValue); + } + } + + private static void assertEquals(Object expect, Object actual) + throws Exception { + if (expect.equals(actual)) + System.out.println("Equal: " + expect); + else + throw new Exception("Expected " + expect + ", got " + actual); + } +} diff -r 6266821dc652 -r 842a7d676774 jdk/test/javax/management/query/QueryDottedAttrTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/management/query/QueryDottedAttrTest.java Tue Mar 11 23:37:02 2008 -0700 @@ -0,0 +1,192 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test QueryDottedAttrTest + * @bug 6602310 + * @summary Test that Query.attr can understand a.b etc. + * @author Eamonn McManus + */ + +import java.beans.ConstructorProperties; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Collections; +import java.util.Set; +import javax.management.AttributeNotFoundException; +import javax.management.MBeanException; +import javax.management.MBeanServer; +import javax.management.MBeanServerFactory; +import javax.management.ObjectName; +import javax.management.Query; +import javax.management.QueryExp; +import javax.management.ReflectionException; +import javax.management.StandardMBean; + +public class QueryDottedAttrTest { + public static class Complex { + private final double re, im; + + @ConstructorProperties({"real", "imaginary"}) + public Complex(double re, double im) { + this.re = re; + this.im = im; + } + + public double getRe() { + return re; + } + + public double getIm() { + return im; + } + } + + public static interface Intf { + Complex getComplex(); + int[] getIntArray(); + String[] getStringArray(); + } + + public static class Impl implements Intf { + public Complex getComplex() { + return new Complex(1.0, 1.0); + } + + public int[] getIntArray() { + return new int[] {1, 2, 3}; + } + + public String[] getStringArray() { + return new String[] {"one", "two", "three"}; + } + } + + public static interface TestMBean extends Intf {} + + public static class Test extends Impl implements TestMBean {} + + public static interface TestMXBean extends Intf {} + + public static class TestMX extends Impl implements TestMXBean {} + + public static class AttrWithDot extends StandardMBean { + public AttrWithDot(Object impl, Class intf) { + super(intf.cast(impl), intf, (intf == TestMXBean.class)); + } + + public Object getAttribute(String attribute) + throws AttributeNotFoundException, MBeanException, ReflectionException { + if (attribute.equals("Complex.re")) + return 2.0; + else + return super.getAttribute(attribute); + } + } + + private static final boolean[] booleans = {false, true}; + + private static final QueryExp[] alwaysTrueQueries = { + Query.eq(Query.attr("IntArray.length"), Query.value(3)), + Query.eq(Query.attr("StringArray.length"), Query.value(3)), + Query.eq(Query.attr("Complex.im"), Query.value(1.0)), + }; + + private static final QueryExp[] alwaysFalseQueries = { + Query.eq(Query.attr("IntArray.length"), Query.value("3")), + Query.eq(Query.attr("IntArray.length"), Query.value(2)), + Query.eq(Query.attr("Complex.im"), Query.value(-1.0)), + Query.eq(Query.attr("Complex.xxx"), Query.value(0)), + }; + + private static final QueryExp[] attrWithDotTrueQueries = { + Query.eq(Query.attr("Complex.re"), Query.value(2.0)), + }; + + private static final QueryExp[] attrWithDotFalseQueries = { + Query.eq(Query.attr("Complex.re"), Query.value(1.0)), + }; + + private static String failure; + + public static void main(String[] args) throws Exception { + ObjectName name = new ObjectName("a:b=c"); + for (boolean attrWithDot : booleans) { + for (boolean mx : booleans) { + String what = + (mx ? "MXBean" : "Standard MBean") + + (attrWithDot ? " having attribute with dot in its name" : ""); + System.out.println("Testing " + what); + Class intf = mx ? TestMXBean.class : TestMBean.class; + Object impl = mx ? new TestMX() : new Test(); + if (attrWithDot) + impl = new AttrWithDot(impl, intf); + MBeanServer mbs = MBeanServerFactory.newMBeanServer(); + mbs.registerMBean(impl, name); + boolean ismx = "true".equals( + mbs.getMBeanInfo(name).getDescriptor().getFieldValue("mxbean")); + if (mx != ismx) + fail("MBean should " + (mx ? "" : "not ") + "be MXBean"); + test(mbs, name, alwaysTrueQueries, true); + test(mbs, name, alwaysFalseQueries, false); + test(mbs, name, attrWithDotTrueQueries, attrWithDot); + test(mbs, name, attrWithDotFalseQueries, !attrWithDot); + } + } + if (failure != null) + throw new Exception("TEST FAILED: " + failure); + } + + private static void test( + MBeanServer mbs, ObjectName name, QueryExp[] queries, boolean expect) + throws Exception { + for (QueryExp query : queries) { + // Serialize and deserialize the query to ensure that its + // serialization is correct + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + ObjectOutputStream oout = new ObjectOutputStream(bout); + oout.writeObject(query); + oout.close(); + ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); + ObjectInputStream oin = new ObjectInputStream(bin); + query = (QueryExp) oin.readObject(); + Set names = mbs.queryNames(null, query); + if (names.isEmpty()) { + if (expect) + fail("Query is false but should be true: " + query); + } else if (names.equals(Collections.singleton(name))) { + if (!expect) + fail("Query is true but should be false: " + query); + } else { + fail("Query returned unexpected set: " + names); + } + } + } + + private static void fail(String msg) { + failure = msg; + System.out.println("..." + msg); + } +} diff -r 6266821dc652 -r 842a7d676774 jdk/test/javax/management/query/QueryExpStringTest.java --- a/jdk/test/javax/management/query/QueryExpStringTest.java Wed Mar 12 09:32:38 2008 +0800 +++ b/jdk/test/javax/management/query/QueryExpStringTest.java Tue Mar 11 23:37:02 2008 -0700 @@ -31,6 +31,10 @@ * @run main QueryExpStringTest */ +// This test is mostly obsolete, since we now have Query.fromString. +// The test includes its own parser, from which Query.fromString was derived. +// The parsers are not identical and the one here is no longer maintained. + import java.util.*; import javax.management.*; @@ -39,6 +43,11 @@ private static final ValueExp attr = Query.attr("attr"), qattr = Query.attr("className", "attr"), + aa = Query.attr("A"), + bb = Query.attr("B"), + cc = Query.attr("C"), + dd = Query.attr("D"), + zero = Query.value(0), classattr = Query.classattr(), simpleString = Query.value("simpleString"), complexString = Query.value("a'b\\'\""), @@ -66,10 +75,14 @@ (StringValueExp) simpleString), initialStar = Query.initialSubString((AttributeValueExp) attr, Query.value("*")), + initialPercent = Query.initialSubString((AttributeValueExp) attr, + Query.value("%")), any = Query.anySubString((AttributeValueExp) attr, (StringValueExp) simpleString), anyStar = Query.anySubString((AttributeValueExp) attr, Query.value("*")), + anyPercent = Query.anySubString((AttributeValueExp) attr, + Query.value("%")), ffinal = Query.finalSubString((AttributeValueExp) attr, (StringValueExp) simpleString), finalMagic = Query.finalSubString((AttributeValueExp) attr, @@ -77,16 +90,20 @@ in = Query.in(intValue, new ValueExp[] {intValue, floatValue}), and = Query.and(gt, lt), or = Query.or(gt, lt), - not = Query.not(gt); + not = Query.not(gt), + aPlusB_PlusC = Query.gt(Query.plus(Query.plus(aa, bb), cc), zero), + aPlus_BPlusC = Query.gt(Query.plus(aa, Query.plus(bb, cc)), zero); // Commented-out tests below require change to implementation private static final Object tests[] = { attr, "attr", - qattr, "className.attr", +// qattr, "className.attr", +// Preceding form now appears as className#attr, an incompatible change +// which we don't mind much because nobody uses the two-arg Query.attr. classattr, "Class", simpleString, "'simpleString'", -// complexString, "'a\\'b\\\\\\'\"'", + complexString, "'a''b\\\''\"'", intValue, "12345678", integerValue, "12345678", longValue, "12345678", @@ -104,16 +121,20 @@ eq, "(12345678) = (2.5)", between, "(12345678) between (2.5) and (2.5)", match, "attr like 'simpleString'", -// initial, "attr like 'simpleString*'", -// initialStar, "attr like '\\\\**'", -// any, "attr like '*simpleString*'", -// anyStar, "attr like '*\\\\**'", -// ffinal, "attr like '*simpleString'", -// finalMagic, "attr like '*\\\\?\\\\*\\\\[\\\\\\\\'", + initial, "attr like 'simpleString%'", + initialStar, "attr like '\\*%'", + initialPercent, "attr like '\\%%'", + any, "attr like '%simpleString%'", + anyStar, "attr like '%\\*%'", + anyPercent, "attr like '%\\%%'", + ffinal, "attr like '%simpleString'", + finalMagic, "attr like '%\\?\\*\\[\\\\'", in, "12345678 in (12345678, 2.5)", and, "((12345678) > (2.5)) and ((12345678) < (2.5))", or, "((12345678) > (2.5)) or ((12345678) < (2.5))", not, "not ((12345678) > (2.5))", + aPlusB_PlusC, "(A + B + C) > (0)", +// aPlus_BPlusC, "(A + (B + C)) > (0)", }; public static void main(String[] args) throws Exception { @@ -185,7 +206,9 @@ throw new Exception("Expected types `attr like string': " + exp + " like " + pat); } - return Query.match((AttributeValueExp) exp, (StringValueExp) pat); + StringValueExp spat = (StringValueExp) pat; + spat = Query.value(translateMatch(spat.getValue())); + return Query.match((AttributeValueExp) exp, spat); } if (skip(ss, " in (")) { @@ -203,6 +226,28 @@ throw new Exception("Expected in or like after expression"); } + private static String translateMatch(String s) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < s.length(); i++) { // logic not correct for wide chars + char c = s.charAt(i); + switch (c) { + case '\\': + sb.append(c).append(s.charAt(++i)); break; + case '%': + sb.append('*'); break; + case '_': + sb.append('?'); break; + case '*': + sb.append("\\*"); break; + case '?': + sb.append("\\?"); break; + default: + sb.append(c); break; + } + } + return sb.toString(); + } + private static QueryExp parseQueryAfterParen(String[] ss) throws Exception { /* This is very ugly. We might have "(q1) and (q2)" here, or @@ -229,7 +274,7 @@ ss[0] = start; ValueExp lhs = parseExp(ss); if (!skip(ss, ") ")) - throw new Exception("Expected `) ' after subexpression"); + throw new Exception("Expected `) ' after subexpression: " + ss[0]); String op = scanWord(ss); if (!skip(ss, " (")) throw new Exception("Expected ` (' after `" + op + "'"); @@ -258,15 +303,16 @@ } private static ValueExp parseExp(String[] ss) throws Exception { - final ValueExp prim = parsePrimary(ss); + ValueExp lhs = parsePrimary(ss); + while (true) { /* Look ahead to see if we have an arithmetic operator. */ String back = ss[0]; if (!skip(ss, " ")) - return prim; + return lhs; if (ss[0].equals("") || "+-*/".indexOf(ss[0].charAt(0)) < 0) { ss[0] = back; - return prim; + return lhs; } final String op = scanWord(ss); @@ -276,15 +322,16 @@ throw new Exception("Unknown arithmetic operator: " + op); if (!skip(ss, " ")) throw new Exception("Expected space after arithmetic operator"); - ValueExp rhs = parseExp(ss); + ValueExp rhs = parsePrimary(ss); switch (op.charAt(0)) { - case '+': return Query.plus(prim, rhs); - case '-': return Query.minus(prim, rhs); - case '*': return Query.times(prim, rhs); - case '/': return Query.div(prim, rhs); + case '+': lhs = Query.plus(lhs, rhs); break; + case '-': lhs = Query.minus(lhs, rhs); break; + case '*': lhs = Query.times(lhs, rhs); break; + case '/': lhs = Query.div(lhs, rhs); break; default: throw new Exception("Can't happen: " + op.charAt(0)); } } + } private static ValueExp parsePrimary(String[] ss) throws Exception { String s = ss[0]; @@ -324,14 +371,19 @@ private static String scanWord(String[] ss) throws Exception { String s = ss[0]; int space = s.indexOf(' '); - if (space < 0) { + int rpar = s.indexOf(')'); + if (space < 0 && rpar < 0) { ss[0] = ""; return s; - } else { - String word = s.substring(0, space); - ss[0] = s.substring(space); - return word; } + int stop; + if (space >= 0 && rpar >= 0) // string has both space and ), stop at first + stop = Math.min(space, rpar); + else // string has only one, stop at it + stop = Math.max(space, rpar); + String word = s.substring(0, stop); + ss[0] = s.substring(stop); + return word; } private static boolean matchWord(String[] ss, String word) @@ -381,13 +433,11 @@ for (i = 0; i < len; i++) { char c = s.charAt(i); if (c == '\'') { - ss[0] = s.substring(i + 1); + ++i; + if (i >= len || s.charAt(i) != '\'') { + ss[0] = s.substring(i); return Query.value(buf.toString()); } - if (c == '\\') { - if (++i == len) - throw new Exception("\\ at end of string"); - c = s.charAt(i); } buf.append(c); } diff -r 6266821dc652 -r 842a7d676774 jdk/test/javax/management/query/QueryParseTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/management/query/QueryParseTest.java Tue Mar 11 23:37:02 2008 -0700 @@ -0,0 +1,778 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test QueryParseTest + * @bug 6602310 6604768 + * @summary Test Query.fromString and Query.toString. + * @author Eamonn McManus + */ + +import java.util.Collections; +import java.util.Set; +import javax.management.Attribute; +import javax.management.AttributeList; +import javax.management.AttributeNotFoundException; +import javax.management.DynamicMBean; +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanInfo; +import javax.management.MBeanServer; +import javax.management.MBeanServerDelegate; +import javax.management.MBeanServerFactory; +import javax.management.ObjectName; +import javax.management.Query; +import javax.management.QueryExp; + +public class QueryParseTest { + // In this table, each string constant corresponds to a test case. + // The objects following the string up to the next string are MBeans. + // Each MBean must implement ExpectedValue to return true or false + // according as it should return that value for the query parsed + // from the given string. The test will parse the string into a + // a query and verify that the MBeans return the expected value + // for that query. Then it will convert the query back into a string + // and into a second query, and check that the MBeans return the + // expected value for that query too. The reason we need to do all + // this is that the spec talks about "equivalent queries", and gives + // the implementation wide scope to rearrange queries. So we cannot + // just compare string values. + // + // We could also write an implementation-dependent test that knew what + // the strings look like, and that would have to be changed if the + // implementation changed. But the approach here is cleaner. + // + // To simplify the creation of MBeans, most use the expectTrue or + // expectFalse methods. The parameters of these methods end up in + // attributes called "A", "B", "C", etc. + private static final Object[] queryTests = { + // RELATIONS + + "A < B", + expectTrue(1, 2), expectTrue(1.0, 2.0), expectTrue("one", "two"), + expectTrue(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY), + expectFalse(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY), + expectFalse(1, 1), expectFalse(1.0, 1.0), expectFalse("one", "one"), + expectFalse(2, 1), expectFalse(2.0, 1.0), expectFalse("two", "one"), + expectFalse(Double.NaN, Double.NaN), + + "One = two", + expectTrueOneTwo(1, 1), expectTrueOneTwo(1.0, 1.0), + expectFalseOneTwo(1, 2), expectFalseOneTwo(2, 1), + + "A <= B", + expectTrue(1, 1), expectTrue(1, 2), expectTrue("one", "one"), + expectTrue("one", "two"), + expectFalse(2, 1), expectFalse("two", "one"), + expectFalse(Double.NaN, Double.NaN), + + "A >= B", + expectTrue(1, 1), expectTrue(2, 1), expectTrue("two", "one"), + expectFalse(1, 2), expectFalse("one", "two"), + + "A > B", + expectTrue(2, 1), expectTrue("two", "one"), + expectFalse(2, 2), expectFalse(1, 2), expectFalse(1.0, 2.0), + expectFalse("one", "two"), + + "A <> B", + expectTrue(1, 2), expectTrue("foo", "bar"), + expectFalse(1, 1), expectFalse("foo", "foo"), + + "A != B", + expectTrue(1, 2), expectTrue("foo", "bar"), + expectFalse(1, 1), expectFalse("foo", "foo"), + + // PARENTHESES + + "(((A))) = (B)", + expectTrue(1, 1), expectFalse(1, 2), + + "(A = B)", + expectTrue(1, 1), expectFalse(1, 2), + + "(((A = (B))))", + expectTrue(1, 1), expectFalse(1, 2), + + // INTEGER LITERALS + + "A = 1234567890123456789", + expectTrue(1234567890123456789L), expectFalse(123456789L), + + "A = +1234567890123456789", + expectTrue(1234567890123456789L), expectFalse(123456789L), + + "A = -1234567890123456789", + expectTrue(-1234567890123456789L), expectFalse(-123456789L), + + + "A = + 1234567890123456789", + expectTrue(1234567890123456789L), expectFalse(123456789L), + + "A = - 1234567890123456789", + expectTrue(-1234567890123456789L), expectFalse(-123456789L), + + "A = " + Long.MAX_VALUE, + expectTrue(Long.MAX_VALUE), expectFalse(Long.MIN_VALUE), + + "A = " + Long.MIN_VALUE, + expectTrue(Long.MIN_VALUE), expectFalse(Long.MAX_VALUE), + + // DOUBLE LITERALS + + "A = 0.0", + expectTrue(0.0), expectFalse(1.0), + + "A = 0.0e23", + expectTrue(0.0), expectFalse(1.0), + + "A = 1.2e3", + expectTrue(1.2e3), expectFalse(1.2), + + "A = +1.2", + expectTrue(1.2), expectFalse(-1.2), + + "A = 1.2e+3", + expectTrue(1.2e3), expectFalse(1.2), + + "A = 1.2e-3", + expectTrue(1.2e-3), expectFalse(1.2), + + "A = 1.2E3", + expectTrue(1.2e3), expectFalse(1.2), + + "A = -1.2e3", + expectTrue(-1.2e3), expectFalse(1.2), + + "A = " + Double.MAX_VALUE, + expectTrue(Double.MAX_VALUE), expectFalse(Double.MIN_VALUE), + + "A = " + -Double.MAX_VALUE, + expectTrue(-Double.MAX_VALUE), expectFalse(-Double.MIN_VALUE), + + "A = " + Double.MIN_VALUE, + expectTrue(Double.MIN_VALUE), expectFalse(Double.MAX_VALUE), + + "A = " + -Double.MIN_VALUE, + expectTrue(-Double.MIN_VALUE), expectFalse(-Double.MAX_VALUE), + + Query.toString( // A = Infinity -> A = (1.0/0.0) + Query.eq(Query.attr("A"), Query.value(Double.POSITIVE_INFINITY))), + expectTrue(Double.POSITIVE_INFINITY), + expectFalse(0.0), expectFalse(Double.NEGATIVE_INFINITY), + + Query.toString( // A = -Infinity -> A = (-1.0/0.0) + Query.eq(Query.attr("A"), Query.value(Double.NEGATIVE_INFINITY))), + expectTrue(Double.NEGATIVE_INFINITY), + expectFalse(0.0), expectFalse(Double.POSITIVE_INFINITY), + + Query.toString( // A < NaN -> A < (0.0/0.0) + Query.lt(Query.attr("A"), Query.value(Double.NaN))), + expectFalse(0.0), expectFalse(Double.NEGATIVE_INFINITY), + expectFalse(Double.POSITIVE_INFINITY), expectFalse(Double.NaN), + + Query.toString( // A >= NaN -> A < (0.0/0.0) + Query.geq(Query.attr("A"), Query.value(Double.NaN))), + expectFalse(0.0), expectFalse(Double.NEGATIVE_INFINITY), + expectFalse(Double.POSITIVE_INFINITY), expectFalse(Double.NaN), + + // STRING LITERALS + + "A = 'blim'", + expectTrue("blim"), expectFalse("blam"), + + "A = 'can''t'", + expectTrue("can't"), expectFalse("cant"), expectFalse("can''t"), + + "A = '''blim'''", + expectTrue("'blim'"), expectFalse("'blam'"), + + "A = ''", + expectTrue(""), expectFalse((Object) null), + + // BOOLEAN LITERALS + + "A = true", + expectTrue(true), expectFalse(false), expectFalse((Object) null), + + "A = TRUE", + expectTrue(true), expectFalse(false), + + "A = TrUe", + expectTrue(true), expectFalse(false), + + "A = false", + expectTrue(false), expectFalse(true), + + "A = fAlSe", + expectTrue(false), expectFalse(true), + + "A = \"true\"", // An attribute called "true" + expectFalse(true), expectFalse(false), expectFalse("\"true\""), + newTester(new String[] {"A", "true"}, new Object[] {2.2, 2.2}, true), + newTester(new String[] {"A", "true"}, new Object[] {2.2, 2.3}, false), + + "A = \"False\"", + expectFalse(true), expectFalse(false), expectFalse("\"False\""), + newTester(new String[] {"A", "False"}, new Object[] {2.2, 2.2}, true), + newTester(new String[] {"A", "False"}, new Object[] {2.2, 2.3}, false), + + // ARITHMETIC + + "A + B = 10", + expectTrue(4, 6), expectFalse(3, 8), + + "A + B = 'blim'", + expectTrue("bl", "im"), expectFalse("bl", "am"), + + "A - B = 10", + expectTrue(16, 6), expectFalse(16, 3), + + "A * B = 10", + expectTrue(2, 5), expectFalse(3, 3), + + "A / B = 10", + expectTrue(70, 7), expectTrue(70.0, 7), expectFalse(70.01, 7), + + "A + B + C = 10", + expectTrue(2, 3, 5), expectFalse(2, 4, 8), + + "A+B+C=10", + expectTrue(2, 3, 5), expectFalse(2, 4, 8), + + "A + B + C + D = 10", + expectTrue(1, 2, 3, 4), expectFalse(2, 3, 4, 5), + + "A + (B + C) = 10", + expectTrue(2, 3, 5), expectFalse(2, 4, 8), + + // It is not correct to rearrange A + (B + C) as A + B + C + // (which means (A + B) + C), because of overflow. + // In particular Query.toString must not do this. + "A + (B + C) = " + Double.MAX_VALUE, // ensure no false associativity + expectTrue(Double.MAX_VALUE, Double.MAX_VALUE, -Double.MAX_VALUE), + expectFalse(-Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE), + + "A * (B * C) < " + Double.MAX_VALUE, // same test for multiplication + expectTrue(Double.MAX_VALUE, Double.MAX_VALUE, Double.MIN_VALUE), + expectFalse(Double.MIN_VALUE, Double.MAX_VALUE, Double.MAX_VALUE), + + "A * B + C = 10", + expectTrue(3, 3, 1), expectTrue(2, 4, 2), expectFalse(1, 2, 3), + + "A*B+C=10", + expectTrue(3, 3, 1), expectTrue(2, 4, 2), expectFalse(1, 2, 3), + + "(A * B) + C = 10", + expectTrue(3, 3, 1), expectTrue(2, 4, 2), expectFalse(1, 2, 3), + + "A + B * C = 10", + expectTrue(1, 3, 3), expectTrue(2, 2, 4), expectFalse(1, 2, 3), + + "A - B * C = 10", + expectTrue(16, 2, 3), expectFalse(15, 2, 2), + + "A + B / C = 10", + expectTrue(5, 15, 3), expectFalse(5, 16, 4), + + "A - B / C = 10", + expectTrue(16, 12, 2), expectFalse(15, 10, 3), + + "A * (B + C) = 10", + expectTrue(2, 2, 3), expectFalse(1, 2, 3), + + "A / (B + C) = 10", + expectTrue(70, 4, 3), expectFalse(70, 3, 5), + + "A * (B - C) = 10", + expectTrue(2, 8, 3), expectFalse(2, 3, 8), + + "A / (B - C) = 10", + expectTrue(70, 11, 4), expectFalse(70, 4, 11), + + "A / B / C = 10", + expectTrue(140, 2, 7), expectFalse(100, 5, 5), + + "A / (B / C) = 10", + expectTrue(70, 14, 2), expectFalse(70, 10, 7), + + // LOGIC + + "A = B or C = D", + expectTrue(1, 1, 2, 3), expectTrue(1, 2, 3, 3), expectTrue(1, 1, 2, 2), + expectFalse(1, 2, 3, 4), expectFalse("!", "!!", "?", "??"), + + "A = B and C = D", + expectTrue(1, 1, 2, 2), + expectFalse(1, 1, 2, 3), expectFalse(1, 2, 3, 3), + + "A = 1 and B = 2 and C = 3", + expectTrue(1, 2, 3), expectFalse(1, 2, 4), + + "A = 1 or B = 2 or C = 3", + expectTrue(1, 2, 3), expectTrue(1, 0, 0), expectTrue(0, 0, 3), + expectFalse(2, 3, 4), + + // grouped as (a and b) or (c and d) + "A = 1 AND B = 2 OR C = 3 AND D = 4", + expectTrue(1, 2, 3, 4), expectTrue(1, 2, 1, 2), expectTrue(3, 4, 3, 4), + expectFalse(3, 4, 1, 2), expectFalse(1, 1, 1, 1), + + "(A = 1 AND B = 2) OR (C = 3 AND D = 4)", + expectTrue(1, 2, 3, 4), expectTrue(1, 2, 1, 2), expectTrue(3, 4, 3, 4), + expectFalse(3, 4, 1, 2), expectFalse(1, 1, 1, 1), + + "(A = 1 or B = 2) AND (C = 3 or C = 4)", + expectTrue(1, 1, 3, 3), expectTrue(2, 2, 4, 4), expectTrue(1, 2, 3, 4), + expectFalse(1, 2, 1, 2), expectFalse(3, 4, 3, 4), + + // LIKE + + "A like 'b%m'", + expectTrue("blim"), expectTrue("bm"), + expectFalse(""), expectFalse("blimmo"), expectFalse("mmm"), + + "A not like 'b%m'", + expectFalse("blim"), expectFalse("bm"), + expectTrue(""), expectTrue("blimmo"), expectTrue("mmm"), + + "A like 'b_m'", + expectTrue("bim"), expectFalse("blim"), + + "A like '%can''t%'", + expectTrue("can't"), + expectTrue("I'm sorry Dave, I'm afraid I can't do that"), + expectFalse("cant"), expectFalse("can''t"), + + "A like '\\%%\\%'", + expectTrue("%blim%"), expectTrue("%%"), + expectFalse("blim"), expectFalse("%asdf"), expectFalse("asdf%"), + + "A LIKE '*%?_'", + expectTrue("*blim?!"), expectTrue("*?_"), + expectFalse("blim"), expectFalse("blim?"), + expectFalse("?*"), expectFalse("??"), expectFalse(""), expectFalse("?"), + + Query.toString( + Query.initialSubString(Query.attr("A"), Query.value("*?%_"))), + expectTrue("*?%_tiddly"), expectTrue("*?%_"), + expectFalse("?%_tiddly"), expectFalse("*!%_"), expectFalse("*??_"), + expectFalse("*?%!"), expectFalse("*?%!tiddly"), + + Query.toString( + Query.finalSubString(Query.attr("A"), Query.value("*?%_"))), + expectTrue("tiddly*?%_"), expectTrue("*?%_"), + expectFalse("tiddly?%_"), expectFalse("*!%_"), expectFalse("*??_"), + expectFalse("*?%!"), expectFalse("tiddly*?%!"), + + // BETWEEN + + "A between B and C", + expectTrue(1, 1, 2), expectTrue(2, 1, 2), expectTrue(2, 1, 3), + expectFalse(3, 1, 2), expectFalse(0, 1, 2), expectFalse(2, 3, 1), + expectTrue(1.0, 0.0, 2.0), expectFalse(2.0, 0.0, 1.0), + expectTrue(0.0, 0.0, 0.0), expectTrue(1.0, 0.0, 1.0), + expectTrue(1.0, 0.0, Double.POSITIVE_INFINITY), + expectFalse(1.0, Double.NEGATIVE_INFINITY, 0.0), + expectFalse(false, false, true), expectFalse(true, false, true), + expectTrue("jim", "fred", "sheila"), expectFalse("fred", "jim", "sheila"), + + "A between B and C and 1+2=3", + expectTrue(2, 1, 3), expectFalse(2, 3, 1), + + "A not between B and C", + expectTrue(1, 2, 3), expectFalse(2, 1, 3), + + // IN + + "A in (1, 2, 3)", + expectTrue(1), expectTrue(2), expectTrue(3), + expectFalse(0), expectFalse(4), + + "A in (1)", + expectTrue(1), expectFalse(0), + + "A in (1.2, 3.4)", + expectTrue(1.2), expectTrue(3.4), expectFalse(0.0), + + "A in ('foo', 'bar')", + expectTrue("foo"), expectTrue("bar"), expectFalse("baz"), + + "A in ('foo', 'bar') and 'bl'+'im'='blim'", + expectTrue("foo"), expectTrue("bar"), expectFalse("baz"), + + "A in (B, C, D)", // requires fix for CR 6604768 + expectTrue(1, 1, 2, 3), expectFalse(1, 2, 3, 4), + + "A not in (B, C, D)", + expectTrue(1, 2, 3, 4), expectFalse(1, 1, 2, 3), + + // QUOTING + + "\"LIKE\" = 1 and \"NOT\" = 2 and \"INSTANCEOF\" = 3 and " + + "\"TRUE\" = 4 and \"FALSE\" = 5", + newTester( + new String[] {"LIKE", "NOT", "INSTANCEOF", "TRUE", "FALSE"}, + new Object[] {1, 2, 3, 4, 5}, + true), + newTester( + new String[] {"LIKE", "NOT", "INSTANCEOF", "TRUE", "FALSE"}, + new Object[] {5, 4, 3, 2, 1}, + false), + + "\"\"\"woo\"\"\" = 5", + newTester(new String[] {"\"woo\""}, new Object[] {5}, true), + newTester(new String[] {"\"woo\""}, new Object[] {4}, false), + expectFalse(), + + // INSTANCEOF + + "instanceof '" + Tester.class.getName() + "'", + expectTrue(), + + "instanceof '" + String.class.getName() + "'", + expectFalse(), + + // LIKE OBJECTNAME + + // The test MBean is registered as a:b=c + "like 'a:b=c'", expectTrue(), + "like 'a:*'", expectTrue(), + "like '*:b=c'", expectTrue(), + "like 'a:b=*'", expectTrue(), + "like 'a:b=?'", expectTrue(), + "like 'd:b=c'", expectFalse(), + "like 'a:b=??*'", expectFalse(), + "like 'a:b=\"can''t\"'", expectFalse(), + + // QUALIFIED ATTRIBUTE + + Tester.class.getName() + "#A = 5", + expectTrue(5), expectFalse(4), + + Tester.class.getName() + " # A = 5", + expectTrue(5), expectFalse(4), + + Tester.class.getSuperclass().getName() + "#A = 5", + expectFalse(5), + + DynamicMBean.class.getName() + "#A = 5", + expectFalse(5), + + Tester.class.getName() + "#A = 5", + new Tester(new String[] {"A"}, new Object[] {5}, false) {}, + // note the little {} at the end which means this is a subclass + // and therefore QualifiedAttributeValue should return false. + + MBeanServerDelegate.class.getName() + "#SpecificationName LIKE '%'", + new Wrapped(new MBeanServerDelegate(), true), + new Tester(new String[] {"SpecificationName"}, new Object[] {"JMX"}, false), + + // DOTTED ATTRIBUTE + + "A.canonicalName = '" + + MBeanServerDelegate.DELEGATE_NAME.getCanonicalName() + "'", + expectTrue(MBeanServerDelegate.DELEGATE_NAME), + expectFalse(ObjectName.WILDCARD), + + "A.class.name = 'java.lang.String'", + expectTrue("blim"), expectFalse(95), expectFalse((Object) null), + + "A.canonicalName like 'JMImpl%:%'", + expectTrue(MBeanServerDelegate.DELEGATE_NAME), + expectFalse(ObjectName.WILDCARD), + + "A.true = 'blim'", + new Tester(new String[] {"A.true"}, new Object[] {"blim"}, true), + new Tester(new String[] {"A.true"}, new Object[] {"blam"}, false), + + "\"A.true\" = 'blim'", + new Tester(new String[] {"A.true"}, new Object[] {"blim"}, true), + new Tester(new String[] {"A.true"}, new Object[] {"blam"}, false), + + MBeanServerDelegate.class.getName() + + "#SpecificationName.class.name = 'java.lang.String'", + new Wrapped(new MBeanServerDelegate(), true), + new Tester(new String[] {"SpecificationName"}, new Object[] {"JMX"}, false), + + MBeanServerDelegate.class.getName() + + " # SpecificationName.class.name = 'java.lang.String'", + new Wrapped(new MBeanServerDelegate(), true), + new Tester(new String[] {"SpecificationName"}, new Object[] {"JMX"}, false), + + // CLASS + + "class = '" + Tester.class.getName() + "'", + expectTrue(), + new Wrapped(new MBeanServerDelegate(), false), + + "Class = '" + Tester.class.getName() + "'", + expectTrue(), + new Wrapped(new MBeanServerDelegate(), false), + }; + + private static final String[] incorrectQueries = { + "", " ", "25", "()", "(a = b", "a = b)", "a.3 = 5", + "a = " + Long.MAX_VALUE + "0", + "a = " + Double.MAX_VALUE + "0", + "a = " + Double.MIN_VALUE + "0", + "a = 12a5", "a = 12e5e5", "a = 12.23.34", + "a = 'can't'", "a = 'unterminated", "a = 'asdf''", + "a = \"oops", "a = \"oops\"\"", + "a like 5", "true or false", + "a ! b", "? = 3", "a = @", "a##b", + "a between b , c", "a between and c", + "a in b, c", "a in 23", "a in (2, 3", "a in (2, 3x)", + "a like \"foo\"", "a like b", "a like 23", + "like \"foo\"", "like b", "like 23", "like 'a:b'", + "5 like 'a'", "'a' like '%'", + "a not= b", "a not = b", "a not b", "a not b c", + "a = +b", "a = +'b'", "a = +true", "a = -b", "a = -'b'", + "a#5 = b", "a#'b' = c", + "a instanceof b", "a instanceof 17", "a instanceof", + "a like 'oops\\'", "a like '[oops'", + + // Check that -Long.MIN_VALUE is an illegal constant. This is one more + // than Long.MAX_VALUE and, like the Java language, we only allow it + // if it is the operand of unary minus. + "a = " + Long.toString(Long.MIN_VALUE).substring(1), + }; + + public static void main(String[] args) throws Exception { + int nexti; + String failed = null; + + System.out.println("TESTING CORRECT QUERY STRINGS"); + for (int i = 0; i < queryTests.length; i = nexti) { + for (nexti = i + 1; nexti < queryTests.length; nexti++) { + if (queryTests[nexti] instanceof String) + break; + } + if (!(queryTests[i] instanceof String)) + throw new Exception("Test bug: should be string: " + queryTests[i]); + + String qs = (String) queryTests[i]; + System.out.println("Test: " + qs); + + QueryExp qe = Query.fromString(qs); + String qes = Query.toString(qe); + System.out.println("...parses to: " + qes); + final QueryExp[] queries; + if (qes.equals(qs)) + queries = new QueryExp[] {qe}; + else { + QueryExp qe2 = Query.fromString(qes); + String qes2 = Query.toString(qe2); + System.out.println("...which parses to: " + qes2); + if (qes.equals(qes2)) + queries = new QueryExp[] {qe}; + else + queries = new QueryExp[] {qe, qe2}; + } + + for (int j = i + 1; j < nexti; j++) { + Object mbean; + if (queryTests[j] instanceof Wrapped) + mbean = ((Wrapped) queryTests[j]).mbean(); + else + mbean = queryTests[j]; + boolean expect = ((ExpectedValue) queryTests[j]).expectedValue(); + for (QueryExp qet : queries) { + boolean actual = runQuery(qet, mbean); + boolean ok = (expect == actual); + System.out.println( + "..." + mbean + " -> " + actual + + (ok ? " (OK)" : " ####INCORRECT####")); + if (!ok) + failed = qs; + } + } + } + + System.out.println(); + System.out.println("TESTING INCORRECT QUERY STRINGS"); + for (String s : incorrectQueries) { + try { + QueryExp qe = Query.fromString(s); + System.out.println("###DID NOT GET ERROR:### \"" + s + "\""); + failed = s; + } catch (IllegalArgumentException e) { + String es = (e.getClass() == IllegalArgumentException.class) ? + e.getMessage() : e.toString(); + System.out.println("OK: exception for \"" + s + "\": " + es); + } + } + + if (failed == null) + System.out.println("TEST PASSED"); + else + throw new Exception("TEST FAILED: Last failure: " + failed); + } + + private static boolean runQuery(QueryExp qe, Object mbean) + throws Exception { + MBeanServer mbs = MBeanServerFactory.newMBeanServer(); + ObjectName name = new ObjectName("a:b=c"); + mbs.registerMBean(mbean, name); + Set names = mbs.queryNames(new ObjectName("a:*"), qe); + if (names.isEmpty()) + return false; + if (names.equals(Collections.singleton(name))) + return true; + throw new Exception("Unexpected query result set: " + names); + } + + private static interface ExpectedValue { + public boolean expectedValue(); + } + + private static class Wrapped implements ExpectedValue { + private final Object mbean; + private final boolean expect; + + Wrapped(Object mbean, boolean expect) { + this.mbean = mbean; + this.expect = expect; + } + + Object mbean() { + return mbean; + } + + public boolean expectedValue() { + return expect; + } + } + + private static class Tester implements DynamicMBean, ExpectedValue { + private final AttributeList attributes; + private final boolean expectedValue; + + Tester(AttributeList attributes, boolean expectedValue) { + this.attributes = attributes; + this.expectedValue = expectedValue; + } + + Tester(String[] names, Object[] values, boolean expectedValue) { + this(makeAttributeList(names, values), expectedValue); + } + + private static AttributeList makeAttributeList( + String[] names, Object[] values) { + if (names.length != values.length) + throw new Error("Test bug: names and values different length"); + AttributeList list = new AttributeList(); + for (int i = 0; i < names.length; i++) + list.add(new Attribute(names[i], values[i])); + return list; + } + + public Object getAttribute(String attribute) + throws AttributeNotFoundException { + for (Attribute a : attributes.asList()) { + if (a.getName().equals(attribute)) + return a.getValue(); + } + throw new AttributeNotFoundException(attribute); + } + + public void setAttribute(Attribute attribute) { + throw new UnsupportedOperationException(); + } + + public AttributeList getAttributes(String[] attributes) { + AttributeList list = new AttributeList(); + for (String attribute : attributes) { + try { + list.add(new Attribute(attribute, getAttribute(attribute))); + } catch (AttributeNotFoundException e) { + // OK: ignore, per semantics of getAttributes + } + } + return list; + } + + public AttributeList setAttributes(AttributeList attributes) { + throw new UnsupportedOperationException(); + } + + public Object invoke(String actionName, Object[] params, String[] signature) { + throw new UnsupportedOperationException(); + } + + public MBeanInfo getMBeanInfo() { + MBeanAttributeInfo mbais[] = new MBeanAttributeInfo[attributes.size()]; + for (int i = 0; i < mbais.length; i++) { + Attribute attr = attributes.asList().get(i); + String name = attr.getName(); + Object value = attr.getValue(); + String type = + ((value == null) ? new Object() : value).getClass().getName(); + mbais[i] = new MBeanAttributeInfo( + name, type, name, true, false, false); + } + return new MBeanInfo( + getClass().getName(), "descr", mbais, null, null, null); + } + + public boolean expectedValue() { + return expectedValue; + } + + @Override + public String toString() { + return attributes.toString(); + } + } + + // Method rather than field, to avoid circular init dependencies + private static String[] abcd() { + return new String[] {"A", "B", "C", "D"}; + } + + private static String[] onetwo() { + return new String[] {"One", "two"}; + } + + private static Object expectTrue(Object... attrs) { + return newTester(abcd(), attrs, true); + } + + private static Object expectFalse(Object... attrs) { + return newTester(abcd(), attrs, false); + } + + private static Object expectTrueOneTwo(Object... attrs) { + return newTester(onetwo(), attrs, true); + } + + private static Object expectFalseOneTwo(Object... attrs) { + return newTester(onetwo(), attrs, false); + } + + private static Object newTester(String[] names, Object[] attrs, boolean expect) { + AttributeList list = new AttributeList(); + for (int i = 0; i < attrs.length; i++) + list.add(new Attribute(names[i], attrs[i])); + return new Tester(list, expect); + } +} diff -r 6266821dc652 -r 842a7d676774 jdk/test/sun/management/jmxremote/bootstrap/JvmstatCountersTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/management/jmxremote/bootstrap/JvmstatCountersTest.java Tue Mar 11 23:37:02 2008 -0700 @@ -0,0 +1,183 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4981215 + * @summary Tests that the jvmstat counters published by the out-of-the-box + * management agent for the JMX connection details are correct. + * @author Luis-Miguel Alventosa + * @run clean JvmstatCountersTest + * @run build JvmstatCountersTest + * @run main/othervm JvmstatCountersTest 1 + * @run main/othervm -Dcom.sun.management.jmxremote JvmstatCountersTest 2 + * @run main/othervm -Dcom.sun.management.jmxremote.port=0 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false JvmstatCountersTest 3 + * @run main/othervm JvmstatCountersTest 4 + */ + +import java.io.*; +import java.lang.management.*; +import java.util.*; +import javax.management.*; +import javax.management.remote.*; +import com.sun.tools.attach.*; +import sun.management.ConnectorAddressLink; + +public class JvmstatCountersTest { + + public static void checkAddress(String address) throws IOException { + System.out.println("Address = " + address); + JMXServiceURL url = new JMXServiceURL(address); + JMXConnector jmxc = JMXConnectorFactory.connect(url); + MBeanServerConnection mbsc = jmxc.getMBeanServerConnection(); + System.out.println("MBean Count = " + mbsc.getMBeanCount()); + } + + public static void checkKey(Map data, int index, + String key, String expectedValue) throws Exception { + String counter = "sun.management.JMXConnectorServer." + index + "." + key; + if (!data.containsKey(counter)) { + System.out.println("Test FAILED! Missing counter " + counter); + throw new IllegalArgumentException("Test case failed"); + } + String value = data.get(counter); + if (key.equals("remoteAddress")) { + checkAddress(value); + } else if (!expectedValue.equals(value)) { + System.out.println("Test FAILED! Invalid counter " + + counter + "=" + value); + throw new IllegalArgumentException("Test case failed"); + } + System.out.println("OK: " + counter + "=" + value); + } + + public static void main(String args[]) throws Exception { + String localAddress = ConnectorAddressLink.importFrom(0); + Map remoteData = ConnectorAddressLink.importRemoteFrom(0); + final int testCase = Integer.parseInt(args[0]); + switch (testCase) { + case 1: + if (localAddress == null && remoteData.isEmpty()) { + System.out.println("Test PASSED! The OOTB management " + + "agent didn't publish any jvmstat counter."); + } else { + System.out.println("Test FAILED! The OOTB management " + + "agent unexpectedly published jvmstat counters."); + throw new IllegalArgumentException("Test case 1 failed"); + } + break; + case 2: + if (localAddress == null) { + System.out.println("Test FAILED! The OOTB management " + + "agent didn't publish the local connector."); + throw new IllegalArgumentException("Test case 2 failed"); + } + checkAddress(localAddress); + if (!remoteData.isEmpty()) { + System.out.println("Test FAILED! The OOTB management " + + "agent shouldn't publish the remote connector."); + throw new IllegalArgumentException("Test case 2 failed"); + } + System.out.println("Test PASSED! The OOTB management " + + "agent only publishes the local connector through " + + "a jvmstat counter."); + break; + case 3: + if (localAddress == null) { + System.out.println("Test FAILED! The OOTB management " + + "agent didn't publish the local connector."); + throw new IllegalArgumentException("Test case 3 failed"); + } + checkAddress(localAddress); + if (remoteData.isEmpty()) { + System.out.println("Test FAILED! The OOTB management " + + "agent didnn't publish the remote connector."); + throw new IllegalArgumentException("Test case 3 failed"); + } + for (String key : remoteData.keySet()) { + if (!key.startsWith("sun.management.JMXConnectorServer.0.")) { + System.out.println("Test FAILED! The OOTB management " + + "agent shouldn't publish anything which isn't " + + "related to the remote connector."); + throw new IllegalArgumentException("Test case 3 failed"); + } + } + checkKey(remoteData, 0, "remoteAddress", null); + checkKey(remoteData, 0, "authenticate", "false"); + checkKey(remoteData, 0, "ssl", "false"); + checkKey(remoteData, 0, "sslRegistry", "false"); + checkKey(remoteData, 0, "sslNeedClientAuth", "false"); + System.out.println("Test PASSED! The OOTB management " + + "agent publishes both the local and remote " + + "connector info through jvmstat counters."); + break; + case 4: + if (localAddress != null || !remoteData.isEmpty()) { + System.out.println("Test FAILED! The OOTB management " + + "agent unexpectedly published jvmstat counters."); + throw new IllegalArgumentException("Test case 4 failed"); + } + RuntimeMXBean rt = ManagementFactory.getRuntimeMXBean(); + String name = rt.getName(); + System.out.println("name = " + name); + String vmid = name.substring(0, name.indexOf("@")); + System.out.println("vmid = " + vmid); + VirtualMachine vm = VirtualMachine.attach(vmid); + String agent = vm.getSystemProperties().getProperty("java.home") + + File.separator + "lib" + File.separator + "management-agent.jar"; + vm.loadAgent(agent, "com.sun.management.jmxremote.port=0,com.sun.management.jmxremote.authenticate=false,com.sun.management.jmxremote.ssl=false"); + vm.detach(); + String localAddress2 = ConnectorAddressLink.importFrom(0); + if (localAddress2 == null) { + System.out.println("Test FAILED! The OOTB management " + + "agent didn't publish the local connector."); + throw new IllegalArgumentException("Test case 4 failed"); + } + checkAddress(localAddress2); + Map remoteData2 = ConnectorAddressLink.importRemoteFrom(0); + if (remoteData2.isEmpty()) { + System.out.println("Test FAILED! The OOTB management " + + "agent didnn't publish the remote connector."); + throw new IllegalArgumentException("Test case 4 failed"); + } + for (String key : remoteData2.keySet()) { + if (!key.startsWith("sun.management.JMXConnectorServer.0.")) { + System.out.println("Test FAILED! The OOTB management " + + "agent shouldn't publish anything which isn't " + + "related to the remote connector."); + throw new IllegalArgumentException("Test case 4 failed"); + } + } + checkKey(remoteData2, 0, "remoteAddress", null); + checkKey(remoteData2, 0, "authenticate", "false"); + checkKey(remoteData2, 0, "ssl", "false"); + checkKey(remoteData2, 0, "sslRegistry", "false"); + checkKey(remoteData2, 0, "sslNeedClientAuth", "false"); + System.out.println("Test PASSED! The OOTB management agent " + + "publishes both the local and remote connector " + + "info through jvmstat counters when the agent is " + + "loaded through the Attach API."); + } + System.out.println("Bye! Bye!"); + } +}