--- a/jdk/make/java/java/mapfile-vers Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/make/java/java/mapfile-vers Mon Mar 17 11:53:36 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;
--- a/jdk/make/java/jli/Makefile Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/make/java/jli/Makefile Mon Mar 17 11:53:36 2008 -0700
@@ -107,6 +107,7 @@
ifeq ($(PLATFORM), windows)
EXTRA_LIBS = advapi32.lib \
+ comctl32.lib \
user32.lib
JAVALIB =
--- a/jdk/make/java/main/java/Makefile Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/make/java/main/java/Makefile Mon Mar 17 11:53:36 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
--- a/jdk/make/java/main/javaw/Makefile Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/make/java/main/javaw/Makefile Mon Mar 17 11:53:36 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)
--- a/jdk/make/tools/src/build/tools/jdwpgen/CommandNode.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/make/tools/src/build/tools/jdwpgen/CommandNode.java Mon Mar 17 11:53:36 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);
}
--- a/jdk/make/tools/src/build/tools/jdwpgen/ConstantSetNode.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/make/tools/src/build/tools/jdwpgen/ConstantSetNode.java Mon Mar 17 11:53:36 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 {
--- a/jdk/make/tools/src/build/tools/jdwpgen/RepeatNode.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/make/tools/src/build/tools/jdwpgen/RepeatNode.java Mon Mar 17 11:53:36 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");
}
--- a/jdk/src/share/bin/java.c Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/bin/java.c Mon Mar 17 11:53:36 2008 -0700
@@ -205,9 +205,7 @@
_wc_enabled = cpwildcard;
_ergo_policy = ergo;
- if (javaw == JNI_TRUE)
- SetJavaw();
-
+ InitLauncher(javaw);
DumpState();
/*
--- a/jdk/src/share/bin/java.h Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/bin/java.h Mon Mar 17 11:53:36 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_ */
--- a/jdk/src/share/bin/main.c Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/bin/main.c Mon Mar 17 11:53:36 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,
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java Mon Mar 17 11:53:36 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);
+ }
+ }
}
--- a/jdk/src/share/classes/com/sun/tools/example/debug/bdi/EventRequestSpec.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/bdi/EventRequestSpec.java Mon Mar 17 11:53:36 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);
--- a/jdk/src/share/classes/com/sun/tools/example/debug/bdi/EventRequestSpecList.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/bdi/EventRequestSpecList.java Mon Mar 17 11:53:36 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<String> 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<SpecListener> specListeners() {
+ return (Vector<SpecListener>)runtime.specListeners.clone();
}
void notifySet(EventRequestSpec spec) {
- Vector l = specListeners();
+ Vector<SpecListener> 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<SpecListener> 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<SpecListener> 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<SpecListener> 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<SpecListener> 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);
}
}
}
--- a/jdk/src/share/classes/com/sun/tools/example/debug/bdi/ExecutionManager.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/bdi/ExecutionManager.java Mon Mar 17 11:53:36 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<String, Connector.Argument> 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<String> methodArgs) {
return specList.createMethodBreakpoint(classPattern,
methodId, methodArgs);
}
@@ -811,7 +802,7 @@
specList.install(spec, vm());
}
- public List eventRequestSpecs() {
+ public List<EventRequestSpec> eventRequestSpecs() {
return specList.eventRequestSpecs();
}
}
--- a/jdk/src/share/classes/com/sun/tools/example/debug/bdi/JDIEventSource.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/bdi/JDIEventSource.java Mon Mar 17 11:53:36 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) {
--- a/jdk/src/share/classes/com/sun/tools/example/debug/bdi/LineBreakpointSpec.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/bdi/LineBreakpointSpec.java Mon Mar 17 11:53:36 2008 -0700
@@ -58,12 +58,12 @@
LineNotFoundException {
Location location = null;
try {
- List locs = clazz.locationsOfLine(lineNumber());
+ List<Location> 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();
}
--- a/jdk/src/share/classes/com/sun/tools/example/debug/bdi/MethodBreakpointSpec.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/bdi/MethodBreakpointSpec.java Mon Mar 17 11:53:36 2008 -0700
@@ -34,11 +34,11 @@
public class MethodBreakpointSpec extends BreakpointSpec {
String methodId;
- List methodArgs;
+ List<String> methodArgs;
MethodBreakpointSpec(EventRequestSpecList specs,
ReferenceTypeSpec refSpec,
- String methodId, List methodArgs) {
+ String methodId, List<String> methodArgs) {
super(specs, refSpec);
this.methodId = methodId;
this.methodArgs = methodArgs;
@@ -76,7 +76,7 @@
return methodId;
}
- public List methodArgs() {
+ public List<String> 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<String> nameList) {
+ List<String> 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<String> argTypeNames = null;
if (methodArgs() != null) {
argTypeNames = new ArrayList<String>(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++;
--- a/jdk/src/share/classes/com/sun/tools/example/debug/bdi/ThreadGroupIterator.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/bdi/ThreadGroupIterator.java Mon Mar 17 11:53:36 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<ThreadGroupReference> {
private final Stack<Iterator<ThreadGroupReference>> stack
= new Stack<Iterator<ThreadGroupReference>>();
@@ -56,8 +56,8 @@
}
*/
- private Iterator top() {
- return (Iterator)stack.peek();
+ private Iterator<ThreadGroupReference> 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;
}
--- a/jdk/src/share/classes/com/sun/tools/example/debug/bdi/ThreadIterator.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/bdi/ThreadIterator.java Mon Mar 17 11:53:36 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<ThreadReference> {
+ Iterator<ThreadReference> 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() {
--- a/jdk/src/share/classes/com/sun/tools/example/debug/expr/LValue.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/expr/LValue.java Mon Mar 17 11:53:36 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<Method> methodsByName(ReferenceType refType,
+ String name, int kind) {
+ List<Method> list = refType.methodsByName(name);
+ Iterator<Method> 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<Type> argTypes, List<Value> arguments) {
if (argTypes.size() != arguments.size()) {
return DIFFERENT;
}
- Iterator typeIter = argTypes.iterator();
- Iterator valIter = arguments.iterator();
+ Iterator<Type> typeIter = argTypes.iterator();
+ Iterator<Value> 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<InterfaceType> 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<Method> overloads,
+ List<Value> 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<Type> 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<Method> overloads;
Method matchingMethod = null;
List<Value> methodArguments = null;
@@ -510,7 +508,7 @@
final ReferenceType refType;
final ThreadReference thread;
final Field matchingField;
- final List overloads;
+ final List<Method> overloads;
Method matchingMethod = null;
List<Value> methodArguments = null;
@@ -765,7 +763,7 @@
static LValue makeNewObject(VirtualMachine vm,
ExpressionParser.GetFrame frameGetter,
String className, List<Value> arguments) throws ParseException {
- List classes = vm.classesByName(className);
+ List<ReferenceType> 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<Method> methods = new ArrayList<Method>(classType.methods()); // writable
- Iterator iter = methods.iterator();
+ Iterator<Method> 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<ReferenceType> 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);
--- a/jdk/src/share/classes/com/sun/tools/example/debug/gui/ClassTreeTool.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/gui/ClassTreeTool.java Mon Mar 17 11:53:36 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) {
--- a/jdk/src/share/classes/com/sun/tools/example/debug/gui/CommandInterpreter.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/gui/CommandInterpreter.java Mon Mar 17 11:53:36 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<Method> 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<String> 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<ReferenceType> 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<ThreadReference> 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<StackFrame> 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<EventRequestSpec> 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<EventRequestSpec> specs = runtime.eventRequestSpecs();
+
+ if (specs.isEmpty()) {
env.notice("No breakpoints set.");
} else {
- List<BreakpointSpec> toDelete = new ArrayList<BreakpointSpec>();
- while (iter.hasNext()) {
- BreakpointSpec spec = (BreakpointSpec)iter.next();
+ List<EventRequestSpec> toDelete = new ArrayList<EventRequestSpec>();
+ 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<Method> 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<LocalVariable> 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);
}
}
}
--- a/jdk/src/share/classes/com/sun/tools/example/debug/gui/JDBFileFilter.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/gui/JDBFileFilter.java Mon Mar 17 11:53:36 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<String> extensions = filters.keys();
if(extensions != null) {
- fullDescription += "." + (String) extensions.nextElement();
+ fullDescription += "." + extensions.nextElement();
while (extensions.hasMoreElements()) {
- fullDescription += ", " + (String) extensions.nextElement();
+ fullDescription += ", " + extensions.nextElement();
}
}
fullDescription += ")";
--- a/jdk/src/share/classes/com/sun/tools/example/debug/gui/LaunchTool.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/gui/LaunchTool.java Mon Mar 17 11:53:36 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<Connector> all = manager.allConnectors();
Map<ButtonModel, Connector> modelToConnector = new HashMap<ButtonModel, Connector>(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<ArgRep> argReps = new ArrayList<ArgRep>(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() +
--- a/jdk/src/share/classes/com/sun/tools/example/debug/gui/SearchPath.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/gui/SearchPath.java Mon Mar 17 11:53:36 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()]);
}
}
--- a/jdk/src/share/classes/com/sun/tools/example/debug/gui/SourceManager.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/gui/SourceManager.java Mon Mar 17 11:53:36 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<SourceModel> 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.
--- a/jdk/src/share/classes/com/sun/tools/example/debug/gui/SourceModel.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/gui/SourceModel.java Mon Mar 17 11:53:36 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);
}
}
--- a/jdk/src/share/classes/com/sun/tools/example/debug/gui/StackTraceTool.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/gui/StackTraceTool.java Mon Mar 17 11:53:36 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();
--- a/jdk/src/share/classes/com/sun/tools/example/debug/gui/ThreadTreeTool.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/gui/ThreadTreeTool.java Mon Mar 17 11:53:36 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<String> 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<String> 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<String> 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<String> tail = threadPath.subList(1, size);
ThreadTreeNode child = findInternalNode(head);
child.removeThread(tail, thread);
if (child.isThreadGroup() && child.getChildCount() < 1) {
--- a/jdk/src/share/classes/com/sun/tools/example/debug/tty/BreakpointSpec.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/tty/BreakpointSpec.java Mon Mar 17 11:53:36 2008 -0700
@@ -34,7 +34,7 @@
class BreakpointSpec extends EventRequestSpec {
String methodId;
- List methodArgs;
+ List<String> methodArgs;
int lineNumber;
BreakpointSpec(ReferenceTypeSpec refSpec, int lineNumber) {
@@ -45,7 +45,7 @@
}
BreakpointSpec(ReferenceTypeSpec refSpec, String methodId,
- List methodArgs) throws MalformedMemberNameException {
+ List<String> methodArgs) throws MalformedMemberNameException {
super(refSpec);
this.methodId = methodId;
this.methodArgs = methodArgs;
@@ -83,7 +83,7 @@
return lineNumber;
}
- List methodArgs() {
+ List<String> 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<Location> 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<String> nameList) {
+ List<String> 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<String> argTypeNames = null;
if (methodArgs() != null) {
argTypeNames = new ArrayList<String>(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++;
--- a/jdk/src/share/classes/com/sun/tools/example/debug/tty/Commands.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/tty/Commands.java Mon Mar 17 11:53:36 2008 -0700
@@ -157,16 +157,16 @@
buf.append(method.name());
buf.append("(");
- List args = method.argumentTypeNames();
+ List<String> 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<Connector> 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<ReferenceType> 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<InterfaceType> 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<Field> fields = cls.allFields();
+ List<Field> 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<ThreadReference> allThreads(ThreadGroupReference group) {
List<ThreadReference> list = new ArrayList<ThreadReference>();
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<StackFrame> 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<EventRequestSpec> parseWatchpointSpec(StringTokenizer t) {
- List<EventRequestSpec> list = new ArrayList<EventRequestSpec>();
+ private List<WatchpointSpec> parseWatchpointSpec(StringTokenizer t) {
+ List<WatchpointSpec> list = new ArrayList<WatchpointSpec>();
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<Method> 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<Location> 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<LocalVariable, Value> 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<Value> 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<ThreadReference> 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<ObjectReference> 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<String> 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<ReferenceType> 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<ReferenceType> 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<ReferenceType, byte[]> map = new HashMap<ReferenceType, byte[]>();
+ Map<ReferenceType, byte[]> map
+ = new HashMap<ReferenceType, byte[]>();
map.put(refType, bytes);
try {
Env.vm().redefineClasses(map);
--- a/jdk/src/share/classes/com/sun/tools/example/debug/tty/Env.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/tty/Env.java Mon Mar 17 11:53:36 2008 -0700
@@ -89,7 +89,7 @@
sourceCache.clear();
}
- static void setSourcePath(List srcList) {
+ static void setSourcePath(List<String> 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<SourceCode> 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<ReferenceType> 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<String> 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);
}
}
}
--- a/jdk/src/share/classes/com/sun/tools/example/debug/tty/EventHandler.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/tty/EventHandler.java Mon Mar 17 11:53:36 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;
--- a/jdk/src/share/classes/com/sun/tools/example/debug/tty/EventRequestSpec.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/tty/EventRequestSpec.java Mon Mar 17 11:53:36 2008 -0700
@@ -101,10 +101,8 @@
* so that is all we need to examine.
*/
ArrayList<ExceptionRequest> deleteList = new ArrayList<ExceptionRequest>();
- 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);
}
--- a/jdk/src/share/classes/com/sun/tools/example/debug/tty/EventRequestSpecList.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/tty/EventRequestSpecList.java Mon Mar 17 11:53:36 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<String> 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;
--- a/jdk/src/share/classes/com/sun/tools/example/debug/tty/SourceMapper.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/tty/SourceMapper.java Mon Mar 17 11:53:36 2008 -0700
@@ -39,15 +39,13 @@
private final String[] dirs;
- SourceMapper(List sourcepath) {
+ SourceMapper(List<String> sourcepath) {
/*
* sourcepath can arrive from the debugee as a List.
* (via PathSearchingVirtualMachine.classPath())
*/
List<String> dirList = new ArrayList<String>();
- 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]);
}
/*
--- a/jdk/src/share/classes/com/sun/tools/example/debug/tty/TTY.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/tty/TTY.java Mon Mar 17 11:53:36 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;
}
--- a/jdk/src/share/classes/com/sun/tools/example/debug/tty/ThreadGroupIterator.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/tty/ThreadGroupIterator.java Mon Mar 17 11:53:36 2008 -0700
@@ -36,7 +36,7 @@
* Descend the tree of thread groups.
* @author Robert G. Field
*/
-class ThreadGroupIterator implements Iterator {
+class ThreadGroupIterator implements Iterator<ThreadGroupReference> {
private final Stack<Iterator<ThreadGroupReference>> stack = new Stack<Iterator<ThreadGroupReference>>();
ThreadGroupIterator(List<ThreadGroupReference> tgl) {
@@ -53,8 +53,8 @@
this(Env.vm().topLevelThreadGroups());
}
- private Iterator top() {
- return (Iterator)stack.peek();
+ private Iterator<ThreadGroupReference> 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;
}
--- a/jdk/src/share/classes/com/sun/tools/example/debug/tty/ThreadInfo.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/tty/ThreadInfo.java Mon Mar 17 11:53:36 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 <code>List</code> of the stack frames.
*/
- List getStack() throws IncompatibleThreadStateException {
+ List<StackFrame> getStack() throws IncompatibleThreadStateException {
return thread.frames();
}
--- a/jdk/src/share/classes/com/sun/tools/example/debug/tty/ThreadIterator.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/tty/ThreadIterator.java Mon Mar 17 11:53:36 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<ThreadReference> {
+ Iterator<ThreadReference> 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() {
--- a/jdk/src/share/classes/com/sun/tools/example/debug/tty/VMConnection.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/tty/VMConnection.java Mon Mar 17 11:53:36 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 "";
}
--- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/ClassQuery.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/ClassQuery.java Mon Mar 17 11:53:36 2008 -0700
@@ -99,8 +99,7 @@
}
out.println("<h2>Instance Data Members:</h2>");
- 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;
--- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/PlatformClasses.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/PlatformClasses.java Mon Mar 17 11:53:36 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;
}
--- a/jdk/src/share/classes/com/sun/tools/jdi/AbstractLauncher.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/jdi/AbstractLauncher.java Mon Mar 17 11:53:36 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;
}
--- a/jdk/src/share/classes/com/sun/tools/jdi/ClassTypeImpl.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/jdi/ClassTypeImpl.java Mon Mar 17 11:53:36 2008 -0700
@@ -95,11 +95,8 @@
}
public List<ClassType> subclasses() {
- List<ReferenceType> all = vm.allClasses();
List<ClassType> subs = new ArrayList<ClassType>();
- 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<? extends Value> 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<Value> 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());
}
--- a/jdk/src/share/classes/com/sun/tools/jdi/ConcreteMethodImpl.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/jdi/ConcreteMethodImpl.java Mon Mar 17 11:53:36 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;
}
--- a/jdk/src/share/classes/com/sun/tools/jdi/EventSetImpl.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/jdi/EventSetImpl.java Mon Mar 17 11:53:36 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() {
--- a/jdk/src/share/classes/com/sun/tools/jdi/JNITypeParser.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/jdi/JNITypeParser.java Mon Mar 17 11:53:36 2008 -0700
@@ -82,7 +82,7 @@
}
String typeName() {
- return (String)typeNameList().get(typeNameList().size()-1);
+ return typeNameList().get(typeNameList().size()-1);
}
List<String> argumentTypeNames() {
@@ -90,7 +90,7 @@
}
String signature() {
- return (String)signatureList().get(signatureList().size()-1);
+ return signatureList().get(signatureList().size()-1);
}
List<String> argumentSignatures() {
--- a/jdk/src/share/classes/com/sun/tools/jdi/MethodImpl.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/jdi/MethodImpl.java Mon Mar 17 11:53:36 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(")");
--- a/jdk/src/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java Mon Mar 17 11:53:36 2008 -0700
@@ -383,7 +383,7 @@
List<Value> 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 " +
--- a/jdk/src/share/classes/com/sun/tools/jdi/PacketStream.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/jdi/PacketStream.java Mon Mar 17 11:53:36 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);
}
--- a/jdk/src/share/classes/com/sun/tools/jdi/ReferenceTypeImpl.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/jdi/ReferenceTypeImpl.java Mon Mar 17 11:53:36 2008 -0700
@@ -59,7 +59,7 @@
private boolean constantPoolInfoGotten = false;
private int constanPoolCount;
private byte[] constantPoolBytes;
- private SoftReference constantPoolBytesRef = null;
+ private SoftReference<byte[]> 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<? extends ReferenceType> inheritedTypes();
void addVisibleFields(List<Field> visibleList, Map<String, Field> visibleTable, List<String> ambiguousNames) {
- List<Field> 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<Field> retList = new ArrayList<Field>(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<String, Method> methodMap, List<Method> 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<String, Method> methodMap);
@@ -549,9 +541,7 @@
public List<Method> methodsByName(String name) {
List<Method> methods = visibleMethods();
ArrayList<Method> retList = new ArrayList<Method>(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<Method> methodsByName(String name, String signature) {
List<Method> methods = visibleMethods();
ArrayList<Method> retList = new ArrayList<Method>(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<String> 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;
}
--- a/jdk/src/share/classes/com/sun/tools/jdi/SDE.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/jdi/SDE.java Mon Mar 17 11:53:36 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')) {
--- a/jdk/src/share/classes/com/sun/tools/jdi/StackFrameImpl.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/jdi/StackFrameImpl.java Mon Mar 17 11:53:36 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++;
--- a/jdk/src/share/classes/com/sun/tools/jdi/TargetVM.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/jdi/TargetVM.java Mon Mar 17 11:53:36 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);
--- a/jdk/src/share/classes/com/sun/tools/jdi/ThreadGroupReferenceImpl.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/jdi/ThreadGroupReferenceImpl.java Mon Mar 17 11:53:36 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();
}
}
--- a/jdk/src/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java Mon Mar 17 11:53:36 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();
}
}
}
--- a/jdk/src/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java Mon Mar 17 11:53:36 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) {
--- a/jdk/src/share/classes/java/io/FileInputStream.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/io/FileInputStream.java Mon Mar 17 11:53:36 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<Boolean> runningFinalize =
- new ThreadLocal<Boolean>();
+ private static final ThreadLocal<Boolean> runningFinalize =
+ new ThreadLocal<Boolean>();
private static boolean isRunningFinalize() {
Boolean val;
@@ -151,7 +151,7 @@
* is thrown.
* <p>
* This constructor does not throw an exception if <code>fdObj</code>
- * 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 <code>IOException</code> 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
--- a/jdk/src/share/classes/java/io/FileOutputStream.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/io/FileOutputStream.java Mon Mar 17 11:53:36 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<Boolean> runningFinalize =
- new ThreadLocal<Boolean>();
+ private static final ThreadLocal<Boolean> runningFinalize =
+ new ThreadLocal<Boolean>();
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 <code>FileDescriptor</code> object is
* created to represent this file connection.
* <p>
@@ -100,8 +96,8 @@
}
/**
- * Creates an output file stream to write to the file with the specified
- * <code>name</code>. If the second argument is <code>true</code>, then
+ * Creates a file output stream to write to the file with the specified
+ * name. If the second argument is <code>true</code>, then
* bytes will be written to the end of the file rather than the beginning.
* A new <code>FileDescriptor</code> 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.
* <p>
@@ -223,7 +214,7 @@
* is thrown.
* <p>
* This constructor does not throw an exception if <code>fdObj</code>
- * 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 <code>IOException</code> 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 {
--- a/jdk/src/share/classes/java/io/ObjectInputStream.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/io/ObjectInputStream.java Mon Mar 17 11:53:36 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<String, Class<?>> primClasses
+ = new HashMap<String, Class<?>>(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<Boolean>() {
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<Void>()
{
- public Object run() throws InvalidObjectException {
+ public Void run() throws InvalidObjectException {
list.obj.validateObject();
return null;
}
--- a/jdk/src/share/classes/java/io/ObjectStreamClass.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/io/ObjectStreamClass.java Mon Mar 17 11:53:36 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<Long>() {
+ public Long run() {
+ return computeDefaultSUID(cl);
}
}
);
@@ -392,8 +392,8 @@
}
if (interrupted) {
AccessController.doPrivileged(
- new PrivilegedAction() {
- public Object run() {
+ new PrivilegedAction<Void>() {
+ 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<Void>() {
+ 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<ClassDataSlot> slots = new ArrayList<ClassDataSlot>();
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<String> fieldNames = new HashSet<String>(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<ObjectStreamField> list = new ArrayList<ObjectStreamField>();
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<MemberSignature>() {
+ 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<MemberSignature>() {
+ 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<MemberSignature>() {
+ 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<Class<?>> typeList = new ArrayList<Class<?>>();
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;
}
--- a/jdk/src/share/classes/java/lang/Class.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/lang/Class.java Mon Mar 17 11:53:36 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<Void>() {
+ 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<Class> list = new java.util.ArrayList();
+ return java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction<Class[]>() {
+ public Class[] run() {
+ List<Class> list = new ArrayList<Class>();
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<Field[]> declaredFields;
+ private volatile transient SoftReference<Field[]> publicFields;
+ private volatile transient SoftReference<Method[]> declaredMethods;
+ private volatile transient SoftReference<Method[]> publicMethods;
+ private volatile transient SoftReference<Constructor<T>[]> declaredConstructors;
+ private volatile transient SoftReference<Constructor<T>[]> publicConstructors;
// Intermediate results for getFields and getMethods
- private volatile transient SoftReference declaredPublicFields;
- private volatile transient SoftReference declaredPublicMethods;
+ private volatile transient SoftReference<Field[]> declaredPublicFields;
+ private volatile transient SoftReference<Method[]> 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<Field[]>(res);
} else {
- declaredFields = new SoftReference(res);
+ declaredFields = new SoftReference<Field[]>(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<Class<?>> 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<Field> fields = new ArrayList<Field>();
if (traversedInterfaces == null) {
- traversedInterfaces = new HashSet();
+ traversedInterfaces = new HashSet<Class<?>>();
}
// 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<Field[]>(res);
}
return res;
}
- private static void addAll(Collection c, Field[] o) {
+ private static void addAll(Collection<Field> 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<T>[] privateGetDeclaredConstructors(boolean publicOnly) {
checkInitted();
- Constructor[] res = null;
+ Constructor<T>[] 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<Constructor<T>[]>(res);
} else {
- declaredConstructors = new SoftReference(res);
+ declaredConstructors = new SoftReference<Constructor<T>[]>(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<Method[]>(res);
} else {
- declaredMethods = new SoftReference(res);
+ declaredMethods = new SoftReference<Method[]>(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<Method[]>(res);
}
return res;
}
@@ -2713,11 +2708,11 @@
private Constructor<T> getConstructor0(Class[] parameterTypes,
int which) throws NoSuchMethodException
{
- Constructor[] constructors = privateGetDeclaredConstructors((which == Member.PUBLIC));
- for (int i = 0; i < constructors.length; i++) {
+ Constructor<T>[] constructors = privateGetDeclaredConstructors((which == Member.PUBLIC));
+ for (Constructor<T> constructor : constructors) {
if (arrayContentsEq(parameterTypes,
- constructors[i].getParameterTypes())) {
- return getReflectionFactory().copyConstructor(constructors[i]);
+ constructor.getParameterTypes())) {
+ return getReflectionFactory().copyConstructor(constructor);
}
}
throw new NoSuchMethodException(getName() + ".<init>" + argumentTypesToString(parameterTypes));
@@ -2767,18 +2762,18 @@
return out;
}
- private static Constructor[] copyConstructors(Constructor[] arg) {
- Constructor[] out = new Constructor[arg.length];
+ private static <U> Constructor<U>[] copyConstructors(Constructor<U>[] arg) {
+ Constructor<U>[] 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<T>[] 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<Void>() {
+ 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<Void>() {
+ public Void run() {
values.setAccessible(true);
return null;
}
--- a/jdk/src/share/classes/java/lang/ClassLoader.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/lang/ClassLoader.java Mon Mar 17 11:53:36 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<String, Certificate[]> package2certs
+ = new Hashtable<String, Certificate[]>(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<Class<?>> classes = new Vector<Class<?>>();
// The initiating protection domains for all classes loaded by this loader
- private Set domains = new HashSet();
+ private Set<ProtectionDomain> domains = new HashSet<ProtectionDomain>();
// 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<String, Package> packages = new HashMap<String, Package>();
/**
* 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<Void>() {
+ 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<URL>(tmp);
}
/**
@@ -1068,7 +1072,7 @@
* @since 1.2
*/
protected Enumeration<URL> 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<URL> getBootstrapResources(String name)
throws IOException
{
- final Enumeration e = getBootstrapClassPath().getResources(name);
- return new Enumeration () {
- public Object nextElement() {
- return ((Resource)e.nextElement()).getURL();
+ final Enumeration<Resource> e = getBootstrapClassPath().getResources(name);
+ return new Enumeration<URL> () {
+ 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<String, Package> map;
synchronized (packages) {
- map = (Map)packages.clone();
+ map = new HashMap<String, Package>(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<String> loadedLibraryNames
+ = new Vector<String>();
+
// Native libraries belonging to system classes.
- private static Vector systemNativeLibraries = new Vector();
+ private static Vector<NativeLibrary> systemNativeLibraries
+ = new Vector<NativeLibrary>();
+
// Native libraries associated with the class loader.
- private Vector nativeLibraries = new Vector();
+ private Vector<NativeLibrary> nativeLibraries
+ = new Vector<NativeLibrary>();
// native libraries being loaded/unloaded.
- private static Stack nativeLibraryContext = new Stack();
+ private static Stack<NativeLibrary> nativeLibraryContext
+ = new Stack<NativeLibrary>();
// 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<Object>() {
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<NativeLibrary> 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<NativeLibrary> 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<String, Boolean> 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<String, Boolean> 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<String, Boolean>();
+ packageAssertionStatus = new HashMap<String, Boolean>();
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<String, Boolean>();
+ packageAssertionStatus = new HashMap<String, Boolean>();
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<ClassLoader> {
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;
}
--- a/jdk/src/share/classes/java/lang/Compiler.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/lang/Compiler.java Mon Mar 17 11:53:36 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<Void>() {
+ public Void run() {
boolean loaded = false;
String jit = System.getProperty("java.compiler");
if ((jit != null) && (!jit.equals("NONE")) &&
--- a/jdk/src/share/classes/java/lang/Long.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/lang/Long.java Mon Mar 17 11:53:36 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
--- a/jdk/src/share/classes/java/lang/Package.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/lang/Package.java Mon Mar 17 11:53:36 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<Package>() {
+ 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<String, Package> pkgs
+ = new HashMap<String, Package>(31);
// Maps each directory or zip file name to its corresponding url
- private static Map urls = new HashMap(10);
+ private static Map<String, URL> urls
+ = new HashMap<String, URL>(10);
// Maps each code source url for a jar file to its manifest
- private static Map mans = new HashMap(10);
+ private static Map<String, Manifest> mans
+ = new HashMap<String, Manifest>(10);
private static native String getSystemPackage0(String name);
private static native String[] getSystemPackages0();
--- a/jdk/src/share/classes/java/lang/Process.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/lang/Process.java Mon Mar 17 11:53:36 2008 -0700
@@ -41,18 +41,24 @@
* <p>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.
+ *
+ * <p>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.
+ *
+ * <p>Where desired, <a href="ProcessBuilder.html#redirect-input">
+ * subprocess I/O can also be redirected</a>
+ * using methods of the {@link ProcessBuilder} class.
*
* <p>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
+ * <p>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.
+ *
+ * <p>If the standard input of the subprocess has been redirected using
+ * {@link ProcessBuilder#redirectInput(Redirect)
+ * ProcessBuilder.redirectInput}
+ * then this method will return a
+ * <a href="ProcessBuilder.html#redirect-input">null output stream</a>.
*
* <p>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.
+ *
+ * <p>If the standard output of the subprocess has been redirected using
+ * {@link ProcessBuilder#redirectOutput(Redirect)
+ * ProcessBuilder.redirectOutput}
+ * then this method will return a
+ * <a href="ProcessBuilder.html#redirect-output">null input stream</a>.
+ *
+ * <p>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.
*
* <p>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.
+ *
+ * <p>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
+ * <a href="ProcessBuilder.html#redirect-output">null input stream</a>.
*
* <p>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();
--- a/jdk/src/share/classes/java/lang/ProcessBuilder.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/lang/ProcessBuilder.java Mon Mar 17 11:53:36 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.
*
- * <p>Each <code>ProcessBuilder</code> instance manages a collection
+ * <p>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 @@
*
* <li>a <i>working directory</i>. The default value is the current
* working directory of the current process, usually the directory
- * named by the system property <code>user.dir</code>.
+ * named by the system property {@code user.dir}.
+ *
+ * <li><a name="redirect-input">a source of <i>standard input</i>.
+ * 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
+ * <i>null output stream</i>, for which:
+ *
+ * <ul>
+ * <li>the {@link OutputStream#write(int) write} methods always
+ * throw {@code IOException}
+ * <li>the {@link OutputStream#close() close} method does nothing
+ * </ul>
+ *
+ * <li><a name="redirect-output">a destination for <i>standard output</i>
+ * and <i>standard error</i>. 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 <i>null input
+ * stream</i>, for which:
+ *
+ * <ul>
+ * <li>the {@link InputStream#read() read} methods always return
+ * {@code -1}
+ * <li>the {@link InputStream#available() available} method always returns
+ * {@code 0}
+ * <li>the {@link InputStream#close() close} method does nothing
+ * </ul>
*
* <li>a <i>redirectErrorStream</i> property. Initially, this property
- * is <code>false</code>, 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
- * <code>true</code>, 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.
+ *
+ * <p>If the value is set to {@code true}, then:
+ *
+ * <ul>
+ * <li>standard error is merged with the standard output and always sent
+ * to the same destination (this makes it easier to correlate error
+ * messages with the corresponding output)
+ * <li>the common destination of standard error and standard output can be
+ * redirected using
+ * {@link #redirectOutput(Redirect) redirectOutput}
+ * <li>any redirection set by the
+ * {@link #redirectError(Redirect) redirectError}
+ * method is ignored when creating a subprocess
+ * <li>the stream returned from {@link Process#getErrorStream()} will
+ * always be a <a href="#redirect-output">null input stream</a>
+ * </ul>
*
* </ul>
*
@@ -87,34 +136,43 @@
* is invoked.
*
* <p><strong>Note that this class is not synchronized.</strong>
- * If multiple threads access a <code>ProcessBuilder</code> instance
+ * If multiple threads access a {@code ProcessBuilder} instance
* concurrently, and at least one of the threads modifies one of the
* attributes structurally, it <i>must</i> be synchronized externally.
*
* <p>Starting a new process which uses the default working directory
* and environment is easy:
*
- * <blockquote><pre>
+ * <pre> {@code
* Process p = new ProcessBuilder("myCommand", "myArg").start();
- * </pre></blockquote>
+ * }</pre>
*
* <p>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:
*
- * <blockquote><pre>
- * ProcessBuilder pb = new ProcessBuilder("myCommand", "myArg1", "myArg2");
- * Map<String, String> env = pb.environment();
+ * <pre> {@code
+ * ProcessBuilder pb =
+ * new ProcessBuilder("myCommand", "myArg1", "myArg2");
+ * Map<String, String> 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();
- * </pre></blockquote>
+ * assert pb.redirectInput() == Redirect.PIPE;
+ * assert pb.redirectOutput().file() == log;
+ * assert p.getInputStream().read() == -1;
+ * }</pre>
*
* <p>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<String,String> environment;
private boolean redirectErrorStream;
+ private Redirect[] redirects;
/**
* Constructs a process builder with the specified operating
* system program and arguments. This constructor does <i>not</i>
- * make a copy of the <code>command</code> 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
- * <code>command</code> corresponds to a valid operating system
- * command.</p>
+ * {@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 <code>null</code>
+ * @param command the list containing the program and its arguments
+ * @throws NullPointerException if the argument is null
*/
public ProcessBuilder(List<String> 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 <code>command</code>
+ * list containing the same strings as the {@code command}
* array, in the same order. It is not checked whether
- * <code>command</code> corresponds to a valid operating system
- * command.</p>
+ * {@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<String>(command.length);
@@ -165,16 +222,15 @@
/**
* Sets this process builder's operating system program and
* arguments. This method does <i>not</i> make a copy of the
- * <code>command</code> 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 <code>command</code> corresponds to a valid
- * operating system command.</p>
+ * 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 <code>null</code>
+ * @throws NullPointerException if the argument is null
*/
public ProcessBuilder command(List<String> 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
- * <code>command</code> array, in the same order. It is not
- * checked whether <code>command</code> corresponds to a valid
- * operating system command.</p>
+ * {@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<String>(command.length);
@@ -205,9 +261,9 @@
* Returns this process builder's operating system program and
* arguments. The returned list is <i>not</i> a copy. Subsequent
* updates to the list will be reflected in the state of this
- * process builder.</p>
+ * process builder.
*
- * @return This process builder's program and its arguments
+ * @return this process builder's program and its arguments
*/
public List<String> command() {
return command;
@@ -225,10 +281,10 @@
* <p>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 <code>ProcessBuilder</code> 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
- * <code>ProcessBuilder</code> instance or the values returned by
+ * {@code ProcessBuilder} instance or the values returned by
* {@link System#getenv System.getenv}.
*
* <p>If the system does not support environment variables, an
@@ -262,25 +318,24 @@
* <p>The returned map is typically case-sensitive on all platforms.
*
* <p>If a security manager exists, its
- * {@link SecurityManager#checkPermission checkPermission}
- * method is called with a
- * <code>{@link RuntimePermission}("getenv.*")</code>
- * 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.
*
* <p>When passing information to a Java subprocess,
* <a href=System.html#EnvironmentVSSystemProperties>system properties</a>
- * are generally preferred over environment variables.</p>
+ * 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<String,String> 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 <code>null</code> -- 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 <code>user.dir</code>,
- * as the working directory of the child process.</p>
+ * 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 <code>null</code> -- 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 <code>user.dir</code>,
- * as the working directory of the child process.</p>
+ * 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 <a href="#redirect-output">null input stream</a>.
+ */
+ static class NullInputStream extends InputStream {
+ public int read() { return -1; }
+ public int available() { return 0; }
+ }
+
+ /**
+ * Implements a <a href="#redirect-input">null output stream</a>.
+ */
+ 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:
+ *
+ * <ul>
+ * <li>the special value {@link #PIPE Redirect.PIPE}
+ * <li>the special value {@link #INHERIT Redirect.INHERIT}
+ * <li>a redirection to read from a file, created by an invocation of
+ * {@link Redirect#from Redirect.from(File)}
+ * <li>a redirection to write to a file, created by an invocation of
+ * {@link Redirect#to Redirect.to(File)}
+ * <li>a redirection to append to a file, created by an invocation of
+ * {@link Redirect#appendTo Redirect.appendTo(File)}
+ * </ul>
+ *
+ * <p>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.
+ *
+ * <p>It will always be true that
+ * <pre> {@code
+ * Redirect.PIPE.file() == null &&
+ * Redirect.PIPE.type() == Redirect.Type.PIPE
+ * }</pre>
+ */
+ 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).
+ *
+ * <p>It will always be true that
+ * <pre> {@code
+ * Redirect.INHERIT.file() == null &&
+ * Redirect.INHERIT.type() == Redirect.Type.INHERIT
+ * }</pre>
+ */
+ 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.
+ *
+ * <p>It will always be true that
+ * <pre> {@code
+ * Redirect.from(file).file() == file &&
+ * Redirect.from(file).type() == Redirect.Type.READ
+ * }</pre>
+ *
+ * @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.
+ *
+ * <p>It will always be true that
+ * <pre> {@code
+ * Redirect.to(file).file() == file &&
+ * Redirect.to(file).type() == Redirect.Type.WRITE
+ * }</pre>
+ *
+ * @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.
+ *
+ * <p>It will always be true that
+ * <pre> {@code
+ * Redirect.appendTo(file).file() == file &&
+ * Redirect.appendTo(file).type() == Redirect.Type.APPEND
+ * }</pre>
+ *
+ * @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.
+ *
+ * <p>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
+ * <a href="#redirect-input">null output stream</a>.
+ *
+ * @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.
+ *
+ * <p>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
+ * <a href="#redirect-output">null input stream</a>.
+ *
+ * @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.
+ *
+ * <p>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
+ * <a href="#redirect-output">null input stream</a>.
+ *
+ * <p>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.
+ *
+ * <p>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.
+ *
+ * <p>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.
+ *
+ * <p>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.
+ *
+ * <p>This is a convenience method. An invocation of the form
+ * <pre> {@code
+ * pb.inheritIO()
+ * }</pre>
+ * behaves in exactly the same way as the invocation
+ * <pre> {@code
+ * pb.redirectInput(Redirect.INHERIT)
+ * .redirectOutput(Redirect.INHERIT)
+ * .redirectError(Redirect.INHERIT)
+ * }</pre>
+ *
+ * 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.
*
- * <p>If this property is <code>true</code>, then any error output
+ * <p>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 <code>false</code>.</p>
+ * The initial value is {@code false}.
*
- * @return This process builder's <code>redirectErrorStream</code> property
+ * @return this process builder's {@code redirectErrorStream} property
*/
public boolean redirectErrorStream() {
return redirectErrorStream;
}
/**
- * Sets this process builder's <code>redirectErrorStream</code> property.
+ * Sets this process builder's {@code redirectErrorStream} property.
*
- * <p>If this property is <code>true</code>, then any error output
+ * <p>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 <code>false</code>.</p>
+ * 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 @@
* <p>If there is a security manager, its
* {@link SecurityManager#checkExec checkExec}
* method is called with the first component of this object's
- * <code>command</code> array as its argument. This may result in
+ * {@code command} array as its argument. This may result in
* a {@link SecurityException} being thrown.
*
* <p>Starting an operating system process is highly system-dependent.
@@ -426,26 +953,42 @@
* subclass of {@link IOException}.
*
* <p>Subsequent modifications to this process builder will not
- * affect the returned {@link Process}.</p>
+ * 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 <code>0</code>)
+ * @throws SecurityException
+ * if a security manager exists and
+ * <ul>
+ *
+ * <li>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
+ * <li>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
+ * <li>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)
+ * </ul>
+ *
+ * @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
--- a/jdk/src/share/classes/java/lang/StringCoding.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/lang/StringCoding.java Mon Mar 17 11:53:36 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<SoftReference<StringDecoder>> decoder =
+ new ThreadLocal<SoftReference<StringDecoder>>();
+ private final static ThreadLocal<SoftReference<StringEncoder>> encoder =
+ new ThreadLocal<SoftReference<StringEncoder>>();
private static boolean warnUnsupportedCharset = true;
- private static Object deref(ThreadLocal tl) {
- SoftReference sr = (SoftReference)tl.get();
+ private static <T> T deref(ThreadLocal<SoftReference<T>> tl) {
+ SoftReference<T> 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 <T> void set(ThreadLocal<SoftReference<T>> tl, T ob) {
+ tl.set(new SoftReference<T>(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) {
--- a/jdk/src/share/classes/java/lang/ref/Finalizer.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/lang/ref/Finalizer.java Mon Mar 17 11:53:36 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<Void>() {
+ 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() */
--- a/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java Mon Mar 17 11:53:36 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}
--- a/jdk/src/share/classes/java/lang/reflect/Modifier.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/lang/reflect/Modifier.java Mon Mar 17 11:53:36 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());
}
--- a/jdk/src/share/classes/java/lang/reflect/Proxy.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/lang/reflect/Proxy.java Mon Mar 17 11:53:36 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<ClassLoader, Map<List<String>, Object>> loaderToCache
+ = new WeakHashMap<ClassLoader, Map<List<String>, 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<Class<?>, Void> proxyClasses =
+ Collections.synchronizedMap(new WeakHashMap<Class<?>, 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<Class<?>> interfaceSet = new HashSet<Class<?>>();
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<String> key = Arrays.asList(interfaceNames);
/*
* Find or create the proxy class cache for the class loader.
*/
- Map cache;
+ Map<List<String>, Object> cache;
synchronized (loaderToCache) {
- cache = (Map) loaderToCache.get(loader);
+ cache = loaderToCache.get(loader);
if (cache == null) {
- cache = new HashMap();
+ cache = new HashMap<List<String>, 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<Class<?>>(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) {
--- a/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java Mon Mar 17 11:53:36 2008 -0700
@@ -664,7 +664,6 @@
abstract void socketSetOption(int cmd, boolean on, Object value)
throws SocketException;
abstract int socketGetOption(int opt, Object iaContainerObj) throws SocketException;
- abstract int socketGetOption1(int opt, Object iaContainerObj, FileDescriptor fd) throws SocketException;
abstract void socketSendUrgentData(int data)
throws IOException;
--- a/jdk/src/share/classes/java/net/DatagramSocket.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/net/DatagramSocket.java Mon Mar 17 11:53:36 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<Void>() {
+ public Void run() throws NoSuchMethodException {
Class[] cl = new Class[1];
cl[0] = DatagramPacket.class;
impl.getClass().getDeclaredMethod("peekData", cl);
--- a/jdk/src/share/classes/java/net/InterfaceAddress.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/net/InterfaceAddress.java Mon Mar 17 11:53:36 2008 -0700
@@ -103,11 +103,9 @@
return false;
}
InterfaceAddress cmp = (InterfaceAddress) obj;
- if ((address != null & cmp.address == null) ||
- (!address.equals(cmp.address)))
+ if ( !(address == null ? cmp.address == null : address.equals(cmp.address)) )
return false;
- if ((broadcast != null & cmp.broadcast == null) ||
- (!broadcast.equals(cmp.broadcast)))
+ if ( !(broadcast == null ? cmp.broadcast == null : broadcast.equals(cmp.broadcast)) )
return false;
if (maskLength != cmp.maskLength)
return false;
--- a/jdk/src/share/classes/java/net/NetworkInterface.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/net/NetworkInterface.java Mon Mar 17 11:53:36 2008 -0700
@@ -425,8 +425,6 @@
return virtual;
}
- private native static long getSubnet0(String name, int ind) throws SocketException;
- private native static Inet4Address getBroadcast0(String name, int ind) throws SocketException;
private native static boolean isUp0(String name, int ind) throws SocketException;
private native static boolean isLoopback0(String name, int ind) throws SocketException;
private native static boolean supportsMulticast0(String name, int ind) throws SocketException;
--- a/jdk/src/share/classes/java/net/ServerSocket.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/net/ServerSocket.java Mon Mar 17 11:53:36 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<Void>() {
+ public Void run() throws NoSuchMethodException {
Class[] cl = new Class[2];
cl[0] = SocketAddress.class;
cl[1] = Integer.TYPE;
--- a/jdk/src/share/classes/java/net/Socket.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/net/Socket.java Mon Mar 17 11:53:36 2008 -0700
@@ -731,7 +731,8 @@
* then this method will continue to return the connected address
* after the socket is closed.
*
- * @return a <code>SocketAddress</code> reprensenting the remote endpoint of this
+
+ * @return a <code>SocketAddress</code> representing the remote endpoint of this
* socket, or <code>null</code> if it is not connected yet.
* @see #getInetAddress()
* @see #getPort()
@@ -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<InputStream>() {
+ 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<OutputStream>() {
+ public OutputStream run() throws IOException {
return impl.getOutputStream();
}
});
--- a/jdk/src/share/classes/java/net/SocksSocketImpl.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/net/SocksSocketImpl.java Mon Mar 17 11:53:36 2008 -0700
@@ -78,8 +78,8 @@
{
try {
AccessController.doPrivileged(
- new java.security.PrivilegedExceptionAction() {
- public Object run() throws IOException {
+ new java.security.PrivilegedExceptionAction<Void>() {
+ 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<PasswordAuthentication>() {
+ 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<ProxySelector>() {
+ 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<ProxySelector>() {
+ 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<Void>() {
+ 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<Void>() {
+ public Void run() throws Exception {
cmdsock = new Socket(new PlainSocketImpl());
cmdsock.connect(new InetSocketAddress(server, port));
cmdIn = cmdsock.getInputStream();
--- a/jdk/src/share/classes/java/net/URLClassLoader.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/net/URLClassLoader.java Mon Mar 17 11:53:36 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<Class>() {
+ 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<URL>() {
+ public URL run() {
return ucp.findResource(name, true);
}
}, acc);
@@ -397,7 +397,7 @@
public Enumeration<URL> findResources(final String name)
throws IOException
{
- final Enumeration e = ucp.findResources(name, true);
+ final Enumeration<URL> e = ucp.findResources(name, true);
return new Enumeration<URL>() {
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<URL>() {
+ 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<Void>() {
+ 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<URLClassLoader>() {
+ 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<URLClassLoader>() {
+ public URLClassLoader run() {
return new FactoryURLClassLoader(urls);
}
});
--- a/jdk/src/share/classes/java/net/URLConnection.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/net/URLConnection.java Mon Mar 17 11:53:36 2008 -0700
@@ -1072,7 +1072,7 @@
* properties to be appended into a single property.
*
* @param key the keyword by which the request is known
- * (e.g., "<code>accept</code>").
+ * (e.g., "<code>Accept</code>").
* @param value the value associated with it.
* @throws IllegalStateException if already connected
* @throws NullPointerException if key is <CODE>null</CODE>
@@ -1096,7 +1096,7 @@
* existing values associated with the same key.
*
* @param key the keyword by which the request is known
- * (e.g., "<code>accept</code>").
+ * (e.g., "<code>Accept</code>").
* @param value the value associated with it.
* @throws IllegalStateException if already connected
* @throws NullPointerException if key is null
@@ -1120,7 +1120,7 @@
* Returns the value of the named general request property for this
* connection.
*
- * @param key the keyword by which the request is known (e.g., "accept").
+ * @param key the keyword by which the request is known (e.g., "Accept").
* @return the value of the named general request property for this
* connection. If key is null, then null is returned.
* @throws IllegalStateException if already connected
@@ -1164,7 +1164,7 @@
* these properties.
*
* @param key the keyword by which the request is known
- * (e.g., "<code>accept</code>").
+ * (e.g., "<code>Accept</code>").
* @param value the value associated with the key.
*
* @see java.net.URLConnection#setRequestProperty(java.lang.String,java.lang.String)
@@ -1183,7 +1183,7 @@
* Returns the value of the default request property. Default request
* properties are set for every connection.
*
- * @param key the keyword by which the request is known (e.g., "accept").
+ * @param key the keyword by which the request is known (e.g., "Accept").
* @return the value of the default request property
* for the specified key.
*
--- a/jdk/src/share/classes/java/nio/channels/Channels.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/nio/channels/Channels.java Mon Mar 17 11:53:36 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 {
--- a/jdk/src/share/classes/java/nio/channels/spi/SelectorProvider.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/nio/channels/spi/SelectorProvider.java Mon Mar 17 11:53:36 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<SelectorProvider>() {
+ public SelectorProvider run() {
if (loadProviderFromProperty())
return provider;
if (loadProviderAsService())
--- a/jdk/src/share/classes/java/nio/charset/Charset.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/nio/charset/Charset.java Mon Mar 17 11:53:36 2008 -0700
@@ -212,36 +212,47 @@
*
* <h4>Terminology</h4>
*
- * <p> The name of this class is taken from the terms used in <a
- * href="http://www.ietf.org/rfc/rfc2278.txt""><i>RFC 2278</i></a>. In that
- * document a <i>charset</i> is defined as the combination of a coded character
- * set and a character-encoding scheme.
+ * <p> The name of this class is taken from the terms used in
+ * <a href="http://www.ietf.org/rfc/rfc2278.txt"><i>RFC 2278</i></a>.
+ * In that document a <i>charset</i> 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
+ * <i>charset</i> as a synonym for <i>coded character set</i>.)
*
* <p> A <i>coded character set</i> 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.
+ *
+ * <p> Some standards have defined a <i>character set</i> 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 <i>character set</i> and <i>coded character set</i>
+ * is rarely used in practice; the former has become a short form for the
+ * latter, including in the Java API specification.
*
- * <p> A <i>character-encoding scheme</i> 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.
+ * <p> A <i>character-encoding scheme</i> 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.
*
* <p> 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 <tt>US-ASCII</tt> 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 <tt>US-ASCII</tt> is both the
+ * name of a coded character set and of the charset that encodes it, while
* <tt>EUC-JP</tt> 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.
*
* <p> 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. </p>
+ * 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. </p>
*
*
* @author Mark Reinhold
--- a/jdk/src/share/classes/java/rmi/activation/ActivationGroupDesc.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/rmi/activation/ActivationGroupDesc.java Mon Mar 17 11:53:36 2008 -0700
@@ -263,7 +263,7 @@
* @since 1.2
*/
public String[] getCommandOptions() {
- return (String[]) options.clone();
+ return options.clone();
}
/**
--- a/jdk/src/share/classes/java/rmi/dgc/VMID.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/rmi/dgc/VMID.java Mon Mar 17 11:53:36 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<byte[]>() {
+ public byte[] run() {
try {
return InetAddress.getLocalHost().getAddress();
} catch (Exception e) {
--- a/jdk/src/share/classes/java/security/AccessControlContext.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/security/AccessControlContext.java Mon Mar 17 11:53:36 2008 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-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
@@ -322,7 +322,7 @@
debug.println("access denied " + perm);
}
- if (Debug.isOn("failure")) {
+ if (Debug.isOn("failure") && debug != null) {
// Want to make sure this is always displayed for failure,
// but do not want to display again if already displayed
// above.
--- a/jdk/src/share/classes/java/security/KeyStore.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/security/KeyStore.java Mon Mar 17 11:53:36 2008 -0700
@@ -789,7 +789,7 @@
* @param alias the alias name
*
* @return the certificate chain (ordered with the user's certificate first
- * and the root certificate authority last), or null if the given alias
+ * followed by zero or more certificate authorities), or null if the given alias
* does not exist or does not contain a certificate chain
*
* @exception KeyStoreException if the keystore has not been initialized
--- a/jdk/src/share/classes/java/security/cert/TrustAnchor.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/security/cert/TrustAnchor.java Mon Mar 17 11:53:36 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 <code>null</code> if not set.
*/
public final byte [] getNameConstraints() {
- return (ncBytes == null ? null : (byte []) ncBytes.clone());
+ return ncBytes == null ? null : ncBytes.clone();
}
/**
--- a/jdk/src/share/classes/java/security/cert/X509CertSelector.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/security/cert/X509CertSelector.java Mon Mar 17 11:53:36 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();
}
}
--- a/jdk/src/share/classes/java/util/ArrayList.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/util/ArrayList.java Mon Mar 17 11:53:36 2008 -0700
@@ -892,7 +892,7 @@
private final AbstractList<E> parent;
private final int parentOffset;
private final int offset;
- private int size;
+ int size;
SubList(AbstractList<E> parent,
int offset, int fromIndex, int toIndex) {
@@ -971,6 +971,7 @@
public ListIterator<E> listIterator(final int index) {
checkForComodification();
rangeCheckForAdd(index);
+ final int offset = this.offset;
return new ListIterator<E>() {
int cursor = index;
--- a/jdk/src/share/classes/java/util/Arrays.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/util/Arrays.java Mon Mar 17 11:53:36 2008 -0700
@@ -1088,7 +1088,7 @@
* <i>mutually comparable</i> (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 <i>mutually comparable</i> using the specified comparator.
*/
public static <T> void sort(T[] a, Comparator<? super T> 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 <T> void sort(T[] a, int fromIndex, int toIndex,
Comparator<? super T> 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<Object[]>());
return buf.toString();
}
--- a/jdk/src/share/classes/java/util/EnumMap.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/util/EnumMap.java Mon Mar 17 11:53:36 2008 -0700
@@ -140,7 +140,7 @@
public EnumMap(EnumMap<K, ? extends V> m) {
keyType = m.keyType;
keyUniverse = m.keyUniverse;
- vals = (Object[]) m.vals.clone();
+ vals = m.vals.clone();
size = m.size;
}
@@ -161,7 +161,7 @@
EnumMap<K, ? extends V> em = (EnumMap<K, ? extends V>) 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;
}
--- a/jdk/src/share/classes/java/util/HashMap.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/util/HashMap.java Mon Mar 17 11:53:36 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 <tt>HashMap</tt> with the specified initial
--- a/jdk/src/share/classes/java/util/Hashtable.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/util/Hashtable.java Mon Mar 17 11:53:36 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-<code>null</code> object can be used as a key or as a value. <p>
*
* To successfully store and retrieve objects from a hashtable, the
@@ -100,9 +100,15 @@
*
* <p>As of the Java 2 platform v1.2, this class was retrofitted to
* implement the {@link Map} interface, making it a member of the
- * <a href="{@docRoot}/../technotes/guides/collections/index.html"> Java
- * Collections Framework</a>. Unlike the new collection
- * implementations, {@code Hashtable} is synchronized.
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ *
+ * Java Collections Framework</a>. 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
--- a/jdk/src/share/classes/java/util/IdentityHashMap.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/util/IdentityHashMap.java Mon Mar 17 11:53:36 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<K,V> m = (IdentityHashMap<K,V>) 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<K> 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<V> 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<Map.Entry<K,V>> i = iterator(); i.hasNext(); ) {
if (c.contains(i.next())) {
i.remove();
modified = true;
--- a/jdk/src/share/classes/java/util/JumboEnumSet.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/util/JumboEnumSet.java Mon Mar 17 11:53:36 2008 -0700
@@ -364,7 +364,7 @@
public EnumSet<E> clone() {
JumboEnumSet<E> result = (JumboEnumSet<E>) super.clone();
- result.elements = (long[]) result.elements.clone();
+ result.elements = result.elements.clone();
return result;
}
}
--- a/jdk/src/share/classes/java/util/Random.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/util/Random.java Mon Mar 17 11:53:36 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");
--- a/jdk/src/share/classes/java/util/TreeSet.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/util/TreeSet.java Mon Mar 17 11:53:36 2008 -0700
@@ -195,7 +195,7 @@
* @since 1.6
*/
public NavigableSet<E> descendingSet() {
- return new TreeSet(m.descendingMap());
+ return new TreeSet<E>(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);
}
/**
--- a/jdk/src/share/classes/java/util/Vector.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/util/Vector.java Mon Mar 17 11:53:36 2008 -0700
@@ -64,15 +64,15 @@
*
* <p>As of the Java 2 platform v1.2, this class was retrofitted to
* implement the {@link List} interface, making it a member of the
- * <a href="{@docRoot}/../technotes/guides/collections/index.html"> Java
- * Collections Framework</a>. Unlike the new collection
- * implementations, {@code Vector} is synchronized.
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>. 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
*/
--- a/jdk/src/share/classes/java/util/WeakHashMap.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/util/WeakHashMap.java Mon Mar 17 11:53:36 2008 -0700
@@ -29,7 +29,8 @@
/**
- * A hashtable-based <tt>Map</tt> implementation with <em>weak keys</em>.
+ * Hash table based implementation of the <tt>Map</tt> interface, with
+ * <em>weak keys</em>.
* An entry in a <tt>WeakHashMap</tt> 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<K,V>[] newTable(int n) {
--- a/jdk/src/share/classes/java/util/concurrent/DelayQueue.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/DelayQueue.java Mon Mar 17 11:53:36 2008 -0700
@@ -69,10 +69,34 @@
implements BlockingQueue<E> {
private transient final ReentrantLock lock = new ReentrantLock();
- private transient final Condition available = lock.newCondition();
private final PriorityQueue<E> q = new PriorityQueue<E>();
/**
+ * 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 <tt>DelayQueue</tt> 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();
--- a/jdk/src/share/classes/java/util/concurrent/ExecutorService.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/ExecutorService.java Mon Mar 17 11:53:36 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.
*
+ * <p>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.
+ *
+ * <p>This method does not wait for actively executing tasks to
+ * terminate. Use {@link #awaitTermination awaitTermination} to
+ * do that.
*
* <p>There are no guarantees beyond best-effort attempts to stop
* processing actively executing tasks. For example, typical
--- a/jdk/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java Mon Mar 17 11:53:36 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.
*
- * <p> Delayed tasks execute no sooner than they are enabled, but
+ * <p>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.
*
+ * <p>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.
+ *
* <p>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<V> 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.
+ *
+ * <p>This method does not wait for previously submitted tasks to
+ * complete execution. Use {@link #awaitTermination awaitTermination}
+ * to do that.
+ *
+ * <p>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.
*
+ * <p>This method does not wait for actively executing tasks to
+ * terminate. Use {@link #awaitTermination awaitTermination} to
+ * do that.
+ *
* <p>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<RunnableScheduledFuture> as a BlockingQueue<Runnable>
+ * Specialized delay queue. To mesh with TPE declarations, this
+ * class must be declared as a BlockingQueue<Runnable> even though
+ * it can only hold RunnableScheduledFutures.
*/
- private static class DelayedWorkQueue
- extends AbstractCollection<Runnable>
+ static class DelayedWorkQueue extends AbstractQueue<Runnable>
implements BlockingQueue<Runnable> {
- private final DelayQueue<RunnableScheduledFuture> dq = new DelayQueue<RunnableScheduledFuture>();
- 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<? super Runnable> c) { return dq.drainTo(c); }
- public int drainTo(Collection<? super Runnable> 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<? super Runnable> 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> T[] toArray(T[] array) { return dq.toArray(array); }
+ public int drainTo(Collection<? super Runnable> 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> 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<Runnable> iterator() {
- return new Iterator<Runnable>() {
- private Iterator<RunnableScheduledFuture> 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<Runnable> {
+ 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;
+ }
}
}
}
--- a/jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java Mon Mar 17 11:53:36 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.
*
+ * <p>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.
*
+ * <p>This method does not wait for actively executing tasks to
+ * terminate. Use {@link #awaitTermination awaitTermination} to
+ * do that.
+ *
* <p>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
--- a/jdk/src/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java Mon Mar 17 11:53:36 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
}
--- a/jdk/src/share/classes/java/util/prefs/AbstractPreferences.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/util/prefs/AbstractPreferences.java Mon Mar 17 11:53:36 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<String, AbstractPreferences> kidCache
+ = new HashMap<String, AbstractPreferences>();
/**
* 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<kids.length; i++)
- s.add(kids[i]);
- return (String[]) s.toArray(EMPTY_STRING_ARRAY);
+ Set<String> s = new TreeSet<String>(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<AbstractPreferences> 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<Boolean>() {
+ 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<EventObject> eventQueue
+ = new LinkedList<EventObject>();
/**
* 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;
--- a/jdk/src/share/classes/java/util/regex/Matcher.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/java/util/regex/Matcher.java Mon Mar 17 11:53:36 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;
}
--- a/jdk/src/share/classes/javax/management/AndQueryExp.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/javax/management/AndQueryExp.java Mon Mar 17 11:53:36 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;
+ }
+
+}
--- a/jdk/src/share/classes/javax/management/AttributeValueExp.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/javax/management/AttributeValueExp.java Mon Mar 17 11:53:36 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 <CODE>AttributeValueExp</CODE> may be used anywhere a <CODE>ValueExp</CODE> is required.
+ * <p>Represents attributes used as arguments to relational constraints.
+ * Instances of this class are usually obtained using {@link Query#attr(String)
+ * Query.attr}.</p>
+ *
+ * <p>An <CODE>AttributeValueExp</CODE> may be used anywhere a
+ * <CODE>ValueExp</CODE> is required.
*
* @since 1.5
*/
@@ -46,6 +51,8 @@
*/
private String attr;
+ private transient int dotIndex;
+
/**
* An <code>AttributeValueExp</code> 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 <CODE>AttributeValueExp</CODE> on an MBean.
+ * <p>Applies the <CODE>AttributeValueExp</CODE> 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}.</p>
*
* @param name The name of the MBean on which the <CODE>AttributeValueExp</CODE> 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.
+ * <p>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.</p>
+ *
+ * <p>Let <em>n</em> be the {@linkplain #getAttributeName attribute
+ * name}. Then this method proceeds as follows. First it calls
+ * {@link MBeanServer#getAttribute getAttribute(name, <em>n</em>)}. If that
+ * generates an {@link AttributeNotFoundException}, and if <em>n</em>
+ * contains at least one dot ({@code .}), then the method calls {@code
+ * getAttribute(name, }<em>n</em>{@code .substring(0, }<em>n</em>{@code
+ * .indexOf('.')))}; in other words it calls {@code getAttribute}
+ * with the substring of <em>n</em> before the first dot. Then it
+ * extracts a component from the retrieved value, as described in the <a
+ * href="monitor/package-summary.html#complex">documentation for the {@code
+ * monitor} package</a>.</p>
+ *
+ * <p>The MBean Server used is the one returned by {@link
+ * QueryEval#getMBeanServer()}.</p>
*
* @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);
+ }
+ }
+
}
--- a/jdk/src/share/classes/javax/management/BetweenQueryExp.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/javax/management/BetweenQueryExp.java Mon Mar 17 11:53:36 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;
+ }
+}
--- a/jdk/src/share/classes/javax/management/BinaryOpValueExp.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/javax/management/BinaryOpValueExp.java Mon Mar 17 11:53:36 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);
}
+
+
+ }
--- a/jdk/src/share/classes/javax/management/BinaryRelQueryExp.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/javax/management/BinaryRelQueryExp.java Mon Mar 17 11:53:36 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:
--- a/jdk/src/share/classes/javax/management/BooleanValueExp.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/javax/management/BooleanValueExp.java Mon Mar 17 11:53:36 2008 -0700
@@ -84,4 +84,10 @@
return this;
}
+ @Deprecated
+ public void setMBeanServer(MBeanServer s) {
+ super.setMBeanServer(s);
+ }
+
+
}
--- a/jdk/src/share/classes/javax/management/InQueryExp.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/javax/management/InQueryExp.java Mon Mar 17 11:53:36 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;
}
}
--- a/jdk/src/share/classes/javax/management/MatchQueryExp.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/javax/management/MatchQueryExp.java Mon Mar 17 11:53:36 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();
}
/*
--- a/jdk/src/share/classes/javax/management/NotQueryExp.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/javax/management/NotQueryExp.java Mon Mar 17 11:53:36 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) + ")";
+ }
+
}
--- a/jdk/src/share/classes/javax/management/NumericValueExp.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/javax/management/NumericValueExp.java Mon Mar 17 11:53:36 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);
+ }
+
}
--- a/jdk/src/share/classes/javax/management/ObjectName.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/javax/management/ObjectName.java Mon Mar 17 11:53:36 2008 -0700
@@ -222,7 +222,8 @@
* @since 1.5
*/
@SuppressWarnings("serial") // don't complain serialVersionUID not constant
-public class ObjectName implements Comparable<ObjectName>, QueryExp {
+public class ObjectName extends ToQueryString
+ implements Comparable<ObjectName>, 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
--- a/jdk/src/share/classes/javax/management/OrQueryExp.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/javax/management/OrQueryExp.java Mon Mar 17 11:53:36 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;
+ }
}
--- a/jdk/src/share/classes/javax/management/QualifiedAttributeValueExp.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/javax/management/QualifiedAttributeValueExp.java Mon Mar 17 11:53:36 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.
+ * <p>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();
}
--- a/jdk/src/share/classes/javax/management/Query.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/javax/management/Query.java Mon Mar 17 11:53:36 2008 -0700
@@ -27,19 +27,346 @@
/**
- * <p>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:</p>
+ * <p>Constructs query object constraints.</p>
+ *
+ * <p>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.</p>
+ *
+ * <p>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
+ * <a href="#ql">below</a> 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.</p>
+ *
+ * <p>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:</p>
+ *
+ * <pre>
+ * QueryExp query =
+ * Query.and(Query.eq(Query.attr("Enabled"), Query.value(true)),
+ * Query.eq(Query.attr("Owner"), Query.value("Duke")));
+ * </pre>
+ *
+ * <p>Here is how you could construct the same {@code QueryExp} using the
+ * Query Language:</p>
*
* <pre>
- * 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'");
* </pre>
*
+ * <p>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.</p>
+ *
+ *
+ * <h4 id="ql">Query Language</h4>
+ *
+ * <p>The query language is closely modeled on the WHERE clause of
+ * SQL SELECT statements. The formal specification of the language
+ * appears <a href="#formal-ql">below</a>, but it is probably easier to
+ * understand it with examples such as the following.</p>
+ *
+ * <dl>
+ * <dt>{@code Message = 'OK'}
+ * <dd>Selects MBeans that have a {@code Message} attribute whose value
+ * is the string {@code OK}.
+ *
+ * <dt>{@code FreeSpacePercent < 10}
+ * <dd>Selects MBeans that have a {@code FreeSpacePercent} attribute whose
+ * value is a number less than 10.
+ *
+ * <dt>{@code FreeSpacePercent < 10 and WarningSent = false}
+ * <dd>Selects the same MBeans as the previous example, but they must
+ * also have a boolean attribute {@code WarningSent} whose value
+ * is false.
+ *
+ * <dt>{@code SpaceUsed > TotalSpace * (2.0 / 3.0)}
+ * <dd>Selects MBeans that have {@code SpaceUsed} and {@code TotalSpace}
+ * attributes where the first is more than two-thirds the second.
+ *
+ * <dt>{@code not (FreeSpacePercent between 10 and 90)}
+ * <dd>Selects MBeans that have a {@code FreeSpacePercent} attribute whose
+ * value is not between 10 and 90, inclusive.
+ *
+ * <dt>{@code FreeSpacePercent not between 10 and 90}
+ * <dd>Another way of writing the previous query.
+ *
+ * <dt>{@code Status in ('STOPPED', 'STARTING', 'STARTED')}
+ * <dd>Selects MBeans that have a {@code Status} attribute whose value
+ * is one of those three strings.
+ *
+ * <dt>{@code Message like 'OK: %'}
+ * <dd>Selects MBeans that have a {@code Message} attribute whose value
+ * is a string beginning with {@code "OK: "}. <b>Notice that the
+ * wildcard characters are SQL's ones.</b> 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.
+ *
+ * <dt>{@code instanceof 'javax.management.NotificationBroadcaster'}
+ * <dd>Selects MBeans that are instances of
+ * {@link javax.management.NotificationBroadcaster}, as reported by
+ * {@link javax.management.MBeanServer#isInstanceOf MBeanServer.isInstanceOf}.
+ *
+ * <dt>{@code like 'mydomain:*'}
+ * <dd>Selects MBeans whose {@link ObjectName}s have the domain {@code mydomain}.
+ *
+ * </dl>
+ *
+ * <p>The last two examples do not correspond to valid SQL syntax, but all
+ * the others do.</p>
+ *
+ * <p>The remainder of this description is a formal specification of the
+ * query language.</p>
+ *
+ *
+ * <h4 id="formal-ql">Lexical elements</h4>
+ *
+ * <p>Keywords such as <b>and</b>, <b>like</b>, and <b>between</b> are not
+ * case sensitive. You can write <b>between</b>, <b>BETWEEN</b>, or
+ * <b>BeTwEeN</b> with the same effect.</p>
+ *
+ * <p>On the other hand, attribute names <i>are</i> case sensitive. The
+ * attribute {@code Name} is not the same as the attribute {@code name}.</p>
+ *
+ * <p>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}.
+ *
+ * <p>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'}.</p>
+ *
+ * <p>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)}.</p>
+ *
+ * <p>Floating-point constants are written using the Java syntax. A
+ * floating-point constant must be a valid input to
+ * {@link Double#valueOf(String)}.</p>
+ *
+ * <p>A boolean constant is either {@code true} or {@code false}, ignoring
+ * case.</p>
+ *
+ * <p>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<b
+ * and 5=c}, but no further spaces can be removed.</p>
+ *
+ *
+ * <h4 id="grammar-ql">Grammar</h4>
+ *
+ * <dl>
+ * <dt id="query">query:
+ * <dd><a href="#andquery">andquery</a> [<b>OR</b> <a href="#query">query</a>]
+ *
+ * <dt id="andquery">andquery:
+ * <dd><a href="#predicate">predicate</a> [<b>AND</b> <a href="#andquery">andquery</a>]
+ *
+ * <dt id="predicate">predicate:
+ * <dd><b>(</b> <a href="#query">query</a> <b>)</b> |<br>
+ * <b>NOT</b> <a href="#predicate">predicate</a> |<br>
+ * <b>INSTANCEOF</b> <a href="#stringvalue">stringvalue</a> |<br>
+ * <b>LIKE</b> <a href="#objectnamepattern">objectnamepattern</a> |<br>
+ * <a href="#value">value</a> <a href="#predrhs">predrhs</a>
+ *
+ * <dt id="predrhs">predrhs:
+ * <dd><a href="#compare">compare</a> <a href="#value">value</a> |<br>
+ * [<b>NOT</b>] <b>BETWEEN</b> <a href="#value">value</a> <b>AND</b>
+ * <a href="#value">value</a> |<br>
+ * [<b>NOT</b>] <b>IN (</b> <a href="#value">value</a>
+ * <a href="#commavalues">commavalues</a> <b>)</b> |<br>
+ * [<b>NOT</b>] <b>LIKE</b> <a href="#stringvalue">stringvalue</a>
+ *
+ * <dt id="commavalues">commavalues:
+ * <dd>[ <b>,</b> <a href="#value">value</a> <a href="#commavalues">commavalues</a> ]
+ *
+ * <dt id="compare">compare:
+ * <dd><b>=</b> | <b><</b> | <b>></b> |
+ * <b><=</b> | <b>>=</b> | <b><></b> | <b>!=</b>
+ *
+ * <dt id="value">value:
+ * <dd><a href="#factor">factor</a> [<a href="#plusorminus">plusorminus</a>
+ * <a href="#value">value</a>]
+ *
+ * <dt id="plusorminus">plusorminus:
+ * <dd><b>+</b> | <b>-</b>
+ *
+ * <dt id="factor">factor:
+ * <dd><a href="#term">term</a> [<a href="#timesordivide">timesordivide</a>
+ * <a href="#factor">factor</a>]
+ *
+ * <dt id="timesordivide">timesordivide:
+ * <dd><b>*</b> | <b>/</b>
+ *
+ * <dt id="term">term:
+ * <dd><a href="#attr">attr</a> | <a href="#literal">literal</a> |
+ * <b>(</b> <a href="#value">value</a> <b>)</b>
+ *
+ * <dt id="attr">attr:
+ * <dd><a href="#name">name</a> [<b>#</b> <a href="#name">name</a>]
+ *
+ * <dt id="name">name:
+ * <dd><a href="#identifier">identifier</a> [<b>.</b><a href="#name">name</a>]
+ *
+ * <dt id="identifier">identifier:
+ * <dd><i>Java-identifier</i> | <i>double-quoted-identifier</i>
+ *
+ * <dt id="literal">literal:
+ * <dd><a href="#booleanlit">booleanlit</a> | <i>longlit</i> |
+ * <i>doublelit</i> | <i>stringlit</i>
+ *
+ * <dt id="booleanlit">booleanlit:
+ * <dd><b>FALSE</b> | <b>TRUE</b>
+ *
+ * <dt id="stringvalue">stringvalue:
+ * <dd><i>stringlit</i>
+ *
+ * <dt id="objectnamepattern">objectnamepattern:
+ * <dd><i>stringlit</i>
+ *
+ * </dl>
+ *
+ *
+ * <h4>Semantics</h4>
+ *
+ * <p>The meaning of the grammar is described in the table below.
+ * This defines a function <i>q</i> that maps a string to a Java object
+ * such as a {@link QueryExp} or a {@link ValueExp}.</p>
+ *
+ * <table border="1" cellpadding="5">
+ * <tr><th>String <i>s</i></th><th><i>q(s)</th></tr>
+ *
+ * <tr><td><i>query1</i> <b>OR</b> <i>query2</i>
+ * <td>{@link Query#or Query.or}(<i>q(query1)</i>, <i>q(query2)</i>)
+ *
+ * <tr><td><i>query1</i> <b>AND</b> <i>query2</i>
+ * <td>{@link Query#and Query.and}(<i>q(query1)</i>, <i>q(query2)</i>)
+ *
+ * <tr><td><b>(</b> <i>queryOrValue</i> <b>)</b>
+ * <td><i>q(queryOrValue)</i>
+ *
+ * <tr><td><b>NOT</b> <i>query</i>
+ * <td>{@link Query#not Query.not}(<i>q(query)</i>)
+ *
+ * <tr><td><b>INSTANCEOF</b> <i>stringLiteral</i>
+ * <td>{@link Query#isInstanceOf Query.isInstanceOf}(<!--
+ * -->{@link Query#value(String) Query.value}(<i>q(stringLiteral)</i>))
+ *
+ * <tr><td><b>LIKE</b> <i>stringLiteral</i>
+ * <td>{@link ObjectName#ObjectName(String) new ObjectName}(<!--
+ * --><i>q(stringLiteral)</i>)
+ *
+ * <tr><td><i>value1</i> <b>=</b> <i>value2</i>
+ * <td>{@link Query#eq Query.eq}(<i>q(value1)</i>, <i>q(value2)</i>)
+ *
+ * <tr><td><i>value1</i> <b><</b> <i>value2</i>
+ * <td>{@link Query#lt Query.lt}(<i>q(value1)</i>, <i>q(value2)</i>)
+ *
+ * <tr><td><i>value1</i> <b>></b> <i>value2</i>
+ * <td>{@link Query#gt Query.gt}(<i>q(value1)</i>, <i>q(value2)</i>)
+ *
+ * <tr><td><i>value1</i> <b><=</b> <i>value2</i>
+ * <td>{@link Query#leq Query.leq}(<i>q(value1)</i>, <i>q(value2)</i>)
+ *
+ * <tr><td><i>value1</i> <b>>=</b> <i>value2</i>
+ * <td>{@link Query#geq Query.geq}(<i>q(value1)</i>, <i>q(value2)</i>)
+ *
+ * <tr><td><i>value1</i> <b><></b> <i>value2</i>
+ * <td>{@link Query#not Query.not}({@link Query#eq Query.eq}(<!--
+ * --><i>q(value1)</i>, <i>q(value2)</i>))
+ *
+ * <tr><td><i>value1</i> <b>!=</b> <i>value2</i>
+ * <td>{@link Query#not Query.not}({@link Query#eq Query.eq}(<!--
+ * --><i>q(value1)</i>, <i>q(value2)</i>))
+ *
+ * <tr><td><i>value1</i> <b>BETWEEN</b> <i>value2</i> AND <i>value3</i>
+ * <td>{@link Query#between Query.between}(<i>q(value1)</i>,
+ * <i>q(value2)</i>, <i>q(value3)</i>)
+ *
+ * <tr><td><i>value1</i> <b>NOT BETWEEN</b> <i>value2</i> AND <i>value3</i>
+ * <td>{@link Query#not Query.not}({@link Query#between Query.between}(<!--
+ * --><i>q(value1)</i>, <i>q(value2)</i>, <i>q(value3)</i>))
+ *
+ * <tr><td><i>value1</i> <b>IN (</b> <i>value2</i>, <i>value3</i> <b>)</b>
+ * <td>{@link Query#in Query.in}(<i>q(value1)</i>,
+ * <code>new ValueExp[] {</code>
+ * <i>q(value2)</i>, <i>q(value3)</i><code>}</code>)
+ *
+ * <tr><td><i>value1</i> <b>NOT IN (</b> <i>value2</i>, <i>value3</i> <b>)</b>
+ * <td>{@link Query#not Query.not}({@link Query#in Query.in}(<i>q(value1)</i>,
+ * <code>new ValueExp[] {</code>
+ * <i>q(value2)</i>, <i>q(value3)</i><code>}</code>))
+ *
+ * <tr><td><i>value</i> <b>LIKE</b> <i>stringLiteral</i>
+ * <td>{@link Query#match Query.match}(<i>q(value)</i>,
+ * <i><a href="#translateWildcards">translateWildcards</a>(q(stringLiteral))</i>)
+ *
+ * <tr><td><i>value</i> <b>NOT LIKE</b> <i>stringLiteral</i>
+ * <td>{@link Query#not Query.not}({@link Query#match Query.match}(<i>q(value)</i>,
+ * <i><a href="#translateWildcards">translateWildcards</a>(q(stringLiteral))</i>))
+ *
+ * <tr><td><i>value1</i> <b>+</b> <i>value2</i>
+ * <td>{@link Query#plus Query.plus}(<i>q(value1)</i>, <i>q(value2)</i>)
+ *
+ * <tr><td><i>value1</i> <b>-</b> <i>value2</i>
+ * <td>{@link Query#minus Query.minus}(<i>q(value1)</i>, <i>q(value2)</i>)
+ *
+ * <tr><td><i>value1</i> <b>*</b> <i>value2</i>
+ * <td>{@link Query#times Query.times}(<i>q(value1)</i>, <i>q(value2)</i>)
+ *
+ * <tr><td><i>value1</i> <b>/</b> <i>value2</i>
+ * <td>{@link Query#div Query.div}(<i>q(value1)</i>, <i>q(value2)</i>)
+ *
+ * <tr><td><i>name</i>
+ * <td>{@link Query#attr(String) Query.attr}(<i>q(name)</i>)
+ *
+ * <tr><td><i>name1<b>#</b>name2</i>
+ * <td>{@link Query#attr(String,String) Query.attr}(<i>q(name1)</i>,
+ * <i>q(name2)</i>)
+ *
+ * <tr><td><b>FALSE</b>
+ * <td>{@link Query#value(boolean) Query.value}(false)
+ *
+ * <tr><td><b>TRUE</b>
+ * <td>{@link Query#value(boolean) Query.value}(true)
+ *
+ * <tr><td><i>decimalLiteral</i>
+ * <td>{@link Query#value(long) Query.value}(<!--
+ * -->{@link Long#valueOf(String) Long.valueOf}(<i>decimalLiteral</i>))
+ *
+ * <tr><td><i>floatingPointLiteral</i>
+ * <td>{@link Query#value(double) Query.value}(<!--
+ * -->{@link Double#valueOf(String) Double.valueOf}(<!--
+ * --><i>floatingPointLiteral</i>))
+ * </table>
+ *
+ * <p id="translateWildcards">Here, <i>translateWildcards</i> 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
+ * <b>LIKE</b> 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}.</p>
+ *
* @since 1.5
*/
public class Query extends Object {
@@ -277,16 +604,12 @@
}
/**
- * <p>Returns a new attribute expression.</p>
- *
- * <p>Evaluating this expression for a given
- * <code>objectName</code> includes performing {@link
- * MBeanServer#getAttribute MBeanServer.getAttribute(objectName,
- * name)}.</p>
+ * <p>Returns a new attribute expression. See {@link AttributeValueExp}
+ * for a detailed description of the semantics of the expression.</p>
*
* @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 @@
}
/**
+ * <p>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}.</p>
+ *
+ * <p>(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.)</p>
+ *
+ * <p>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.</p>
+ *
+ * @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();
+ }
+
+ /**
+ * <p>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}.</p>
+ *
+ * @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.
*/
--- a/jdk/src/share/classes/javax/management/QueryEval.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/javax/management/QueryEval.java Mon Mar 17 11:53:36 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;
--- a/jdk/src/share/classes/javax/management/QueryExp.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/javax/management/QueryExp.java Mon Mar 17 11:53:36 2008 -0700
@@ -30,9 +30,9 @@
/**
- * <p>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.</p>
+ * <p>Represents relational constraints similar to database query "where
+ * clauses". Instances of QueryExp are returned by the static methods of the
+ * {@link Query} class.</p>
*
* <p>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 {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/javax/management/QueryParser.java Mon Mar 17 11:53:36 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;
+
+/**
+ * <p>Parser for JMX queries represented in an SQL-like language.</p>
+ */
+/*
+ * 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("<end of string>"),
+ 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<String> idKeywords =
+ new TreeSet<String>(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<Token> 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<Token>();
+ 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<ValueExp> values = new ArrayList<ValueExp>();
+ 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);
+ }
+}
--- a/jdk/src/share/classes/javax/management/StringValueExp.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/javax/management/StringValueExp.java Mon Mar 17 11:53:36 2008 -0700
@@ -73,7 +73,7 @@
* Returns the string representing the object.
*/
public String toString() {
- return "'" + val + "'";
+ return "'" + val.replace("'", "''") + "'";
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/javax/management/ToQueryString.java Mon Mar 17 11:53:36 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();
+ }
+}
--- a/jdk/src/share/classes/javax/management/monitor/Monitor.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/javax/management/monitor/Monitor.java Mon Mar 17 11:53:36 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) {
--- a/jdk/src/share/classes/javax/management/remote/JMXServiceURL.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/javax/management/remote/JMXServiceURL.java Mon Mar 17 11:53:36 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
* <code>port</code> is negative.
*/
+ @ConstructorProperties({"protocol", "host", "port", "URLPath"})
public JMXServiceURL(String protocol, String host, int port,
String urlPath)
throws MalformedURLException {
--- a/jdk/src/share/classes/javax/rmi/ssl/SslRMIClientSocketFactory.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/javax/rmi/ssl/SslRMIClientSocketFactory.java Mon Mar 17 11:53:36 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, ",");
--- a/jdk/src/share/classes/javax/rmi/ssl/SslRMIServerSocketFactory.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/javax/rmi/ssl/SslRMIServerSocketFactory.java Mon Mar 17 11:53:36 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<String> 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<String> 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<String> enabledCipherSuitesList;
+ private List<String> enabledProtocolsList;
private SSLContext context;
}
--- a/jdk/src/share/classes/javax/security/auth/kerberos/KerberosTicket.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/javax/security/auth/kerberos/KerberosTicket.java Mon Mar 17 11:53:36 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. */
--- a/jdk/src/share/classes/javax/security/auth/kerberos/KeyImpl.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/javax/security/auth/kerberos/KeyImpl.java Mon Mar 17 11:53:36 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 {
--- a/jdk/src/share/classes/javax/security/cert/X509Certificate.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/javax/security/cert/X509Certificate.java Mon Mar 17 11:53:36 2008 -0700
@@ -363,7 +363,7 @@
* subject Name
* </pre>
*
- * <p>See <a href = "#getIssuerDN">getIssuerDN</a> for <code>Name</code>
+ * <p>See {@link #getIssuerDN() getIssuerDN} for <code>Name</code>
* and other relevant definitions.
*
* @return a Principal whose name is the subject name.
@@ -393,7 +393,7 @@
/**
* Gets the <code>notAfter</code> date from the validity period of
- * the certificate. See <a href = "#getNotBefore">getNotBefore</a>
+ * the certificate. See {@link #getNotBefore() getNotBefore}
* for relevant ASN.1 definitions.
*
* @return the end date of the validity period.
@@ -429,7 +429,7 @@
* For example, the string "1.2.840.10040.4.3" identifies the SHA-1
* with DSA signature algorithm, as per the PKIX part I.
*
- * <p>See <a href = "#getSigAlgName">getSigAlgName</a> for
+ * <p>See {@link #getSigAlgName() getSigAlgName} for
* relevant ASN.1 definitions.
*
* @return the signature algorithm OID string.
@@ -442,7 +442,7 @@
* algorithm parameters are null; the parameters are usually
* supplied with the certificate's public key.
*
- * <p>See <a href = "#getSigAlgName">getSigAlgName</a> for
+ * <p>See {@link #getSigAlgName() getSigAlgName} for
* relevant ASN.1 definitions.
*
* @return the DER-encoded signature algorithm parameters, or
--- a/jdk/src/share/classes/sun/management/ConnectorAddressLink.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/management/ConnectorAddressLink.java Mon Mar 17 11:53:36 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.<counter>.<key>=<value>
+ *
+ * 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 <code>0</code> to indicate
- * the current Java virtual machine.
+ * @param vmid an identifier that uniquely identifies a local Java virtual
+ * machine, or <code>0</code> to indicate the current Java virtual machine.
*
- * @return the value of the connector address, or <code>null</code>
- * if the target VM has not exported a connector address.
+ * @return the value of the connector address, or <code>null</code> 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<String, String> properties) {
+ final int index = counter.getAndIncrement();
+ Perf perf = Perf.getPerf();
+ for (Map.Entry<String, String> 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 <code>0</code> 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<String, String> 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<String, String> properties = new HashMap<String, String>();
+ 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;
+ }
}
--- a/jdk/src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java Mon Mar 17 11:53:36 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;
+ }
+
+ /**
* <p>Prevents our RMI server objects from keeping the JVM alive.</p>
*
* <p>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.</p>
*/
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<String> principalsStr = new HashSet<String>();
- 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<String, Object> 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<String, String> properties = new HashMap<String, String>();
+ 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);
-
}
--- a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmMemPoolEntryImpl.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmMemPoolEntryImpl.java Mon Mar 17 11:53:36 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;
}
/**
--- a/jdk/src/share/classes/sun/misc/ClassFileTransformer.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/misc/ClassFileTransformer.java Mon Mar 17 11:53:36 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<ClassFileTransformer> transformerList
+ = new ArrayList<ClassFileTransformer>();
+ 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
--- a/jdk/src/share/classes/sun/misc/Cleaner.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/misc/Cleaner.java Mon Mar 17 11:53:36 2008 -0700
@@ -141,8 +141,8 @@
try {
thunk.run();
} catch (final Throwable x) {
- AccessController.doPrivileged(new PrivilegedAction() {
- public Object run() {
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ public Void run() {
if (System.err != null)
new Error("Cleaner terminated abnormally", x)
.printStackTrace();
--- a/jdk/src/share/classes/sun/misc/ExtensionDependency.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/misc/ExtensionDependency.java Mon Mar 17 11:53:36 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<Manifest>() {
+ 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<File>() {
+ 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<File> urls = new Vector<File>();
for (int i = 0; i < dirs.length; i++) {
String[] files = dirs[i].list(new JarFilter());
if (files != null) {
@@ -484,16 +483,15 @@
* </p>
*/
private File[] getInstalledExtensions() throws IOException {
- return (File[]) AccessController.doPrivileged
- (
- new PrivilegedAction() {
- public Object run() {
+ return AccessController.doPrivileged(
+ new PrivilegedAction<File[]>() {
+ 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];
}
}
});
--- a/jdk/src/share/classes/sun/misc/GC.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/misc/GC.java Mon Mar 17 11:53:36 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<Void> pa = new PrivilegedAction<Void>() {
+ 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<LatencyRequest> {
/* 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<LatencyRequest> 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<LatencyRequest>();
}
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);
--- a/jdk/src/share/classes/sun/misc/JavaIOFileDescriptorAccess.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/misc/JavaIOFileDescriptorAccess.java Mon Mar 17 11:53:36 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);
}
--- a/jdk/src/share/classes/sun/misc/Launcher.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/misc/Launcher.java Mon Mar 17 11:53:36 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<ExtClassLoader>() {
+ 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<URL> urls = new Vector<URL>();
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<AppClassLoader>() {
+ 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<URL[]>() {
+ public URL[] run() {
File[] classPath = getClassPath(path);
int len = classPath.length;
- Set seenDirs = new HashSet();
+ Set<File> seenDirs = new HashSet<File>();
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<Void>() {
+ 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<Permission> elements() {
if (perms == null)
init();
synchronized (perms) {
--- a/jdk/src/share/classes/sun/misc/PerformanceLogger.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/misc/PerformanceLogger.java Mon Mar 17 11:53:36 2008 -0700
@@ -78,7 +78,7 @@
private static boolean perfLoggingOn = false;
private static boolean useNanoTime = false;
- private static Vector times;
+ private static Vector<TimeData> 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<Void>() {
+ 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<TimeData>(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");
--- a/jdk/src/share/classes/sun/misc/ProxyGenerator.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/misc/ProxyGenerator.java Mon Mar 17 11:53:36 2008 -0700
@@ -324,8 +324,8 @@
if (saveGeneratedFiles) {
java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction() {
- public Object run() {
+ new java.security.PrivilegedAction<Void>() {
+ 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<Class> legalExceptions = new ArrayList<Class>();
+ List<Class<?>> legalExceptions = new ArrayList<Class<?>>();
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<Class> uncoveredReturnTypes = new LinkedList<Class>();
+ LinkedList<Class<?>> uncoveredReturnTypes = new LinkedList<Class<?>>();
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<Class> liter = uncoveredReturnTypes.listIterator();
+ ListIterator<Class<?>> 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<Class> catchList = computeUniqueCatchList(exceptionTypes);
+ List<Class<?>> 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<Class> list)
+ private static void collectCompatibleTypes(Class<?>[] from,
+ Class<?>[] with,
+ List<Class<?>> 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<Class> computeUniqueCatchList(Class[] exceptions) {
- List<Class> uniqueList = new ArrayList<Class>();
+ private static List<Class<?>> computeUniqueCatchList(Class<?>[] exceptions) {
+ List<Class<?>> uniqueList = new ArrayList<Class<?>>();
// 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
--- a/jdk/src/share/classes/sun/misc/URLClassPath.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/misc/URLClassPath.java Mon Mar 17 11:53:36 2008 -0700
@@ -86,16 +86,16 @@
}
/* The original search path of URLs. */
- private ArrayList path = new ArrayList();
+ private ArrayList<URL> path = new ArrayList<URL>();
/* The stack of unopened URLs */
- Stack urls = new Stack();
+ Stack<URL> urls = new Stack<URL>();
/* The resulting search path of Loaders */
- ArrayList loaders = new ArrayList();
+ ArrayList<Loader> loaders = new ArrayList<Loader>();
/* Map of each URL opened to its corresponding Loader */
- HashMap lmap = new HashMap();
+ HashMap<URL, Loader> lmap = new HashMap<URL, Loader>();
/* 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<URL> findResources(final String name,
final boolean check) {
- return new Enumeration() {
+ return new Enumeration<URL>() {
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<Resource> getResources(final String name,
final boolean check) {
- return new Enumeration() {
+ return new Enumeration<Resource>() {
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<Resource> 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<Loader>() {
+ 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<URL, Loader> 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<URL, Loader> 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<Void>() {
+ 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<JarEntry> 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<URL> visited = new HashSet<URL>();
return getResource(name, check, visited);
}
@@ -790,7 +791,7 @@
* non-existent resource
*/
Resource getResource(final String name, boolean check,
- Set visited) {
+ Set<URL> 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<JarLoader>() {
+ public JarLoader run() throws IOException {
return new JarLoader(url, handler,
lmap);
}
--- a/jdk/src/share/classes/sun/net/NetProperties.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/net/NetProperties.java Mon Mar 17 11:53:36 2008 -0700
@@ -42,8 +42,8 @@
static private Properties props = new Properties();
static {
AccessController.doPrivileged(
- new PrivilegedAction() {
- public Object run() {
+ new PrivilegedAction<Void>() {
+ public Void run() {
loadDefaultProperties();
return null;
}});
--- a/jdk/src/share/classes/sun/net/NetworkClient.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/net/NetworkClient.java Mon Mar 17 11:53:36 2008 -0700
@@ -64,8 +64,8 @@
final String encs[] = { null };
AccessController.doPrivileged(
- new PrivilegedAction() {
- public Object run() {
+ new PrivilegedAction<Void>() {
+ 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<Socket>() {
+ public Socket run() {
return new Socket(proxy);
}});
} else
--- a/jdk/src/share/classes/sun/net/ftp/FtpClient.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/net/ftp/FtpClient.java Mon Mar 17 11:53:36 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<Void>() {
+ 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<Socket>() {
+ public Socket run() {
return new Socket(proxy);
}});
} else
--- a/jdk/src/share/classes/sun/net/spi/DefaultProxySelector.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/net/spi/DefaultProxySelector.java Mon Mar 17 11:53:36 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<Boolean>() {
+ 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<Proxy>() {
+ public Proxy run() {
int i, j;
String phost = null;
int pport = 0;
--- a/jdk/src/share/classes/sun/net/www/MessageHeader.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/net/www/MessageHeader.java Mon Mar 17 11:53:36 2008 -0700
@@ -138,7 +138,7 @@
return null;
}
- class HeaderIterator implements Iterator {
+ class HeaderIterator implements Iterator<String> {
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<String> multiValueIterator (String k) {
return new HeaderIterator (k, this);
}
- public synchronized Map getHeaders() {
+ public synchronized Map<String, List<String>> getHeaders() {
return getHeaders(null);
}
- public synchronized Map getHeaders(String[] excludeList) {
+ public synchronized Map<String, List<String>> getHeaders(String[] excludeList) {
boolean skipIt = false;
- Map m = new HashMap();
+ Map<String, List<String>> m = new HashMap<String, List<String>>();
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<String> l = m.get(keys[i]);
if (l == null) {
- l = new ArrayList();
+ l = new ArrayList<String>();
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);
--- a/jdk/src/share/classes/sun/net/www/MimeTable.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/net/www/MimeTable.java Mon Mar 17 11:53:36 2008 -0700
@@ -37,18 +37,20 @@
public class MimeTable implements FileNameMap {
/** Keyed by content type, returns MimeEntries */
- private Hashtable entries = new Hashtable();
+ private Hashtable<String, MimeEntry> entries
+ = new Hashtable<String, MimeEntry>();
/** Keyed by file extension (with the .), returns MimeEntries */
- private Hashtable extensionMap = new Hashtable();
+ private Hashtable<String, MimeEntry> extensionMap
+ = new Hashtable<String, MimeEntry>();
// 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<Void>() {
+ 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<Void>() {
+ 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<MimeEntry> 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<MimeEntry> 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<MimeEntry> 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<MimeEntry> e = elements();
while (e.hasMoreElements()) {
- MimeEntry entry = (MimeEntry)e.nextElement();
+ MimeEntry entry = e.nextElement();
properties.put(entry.getType(), entry.toProperty());
}
--- a/jdk/src/share/classes/sun/net/www/http/ChunkedOutputStream.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/net/www/http/ChunkedOutputStream.java Mon Mar 17 11:53:36 2008 -0700
@@ -177,14 +177,23 @@
return;
}
- if (len > MAX_BUF_SIZE) {
+ int l = preferredChunkSize - count;
+
+ if ((len > MAX_BUF_SIZE) && (len > l)) {
+ /* current chunk is empty just write the data */
+ if (count == 0) {
+ count = len;
+ flush (b, false, off);
+ return;
+ }
+
/* first finish the current chunk */
- int l = preferredChunkSize - count;
if (l > 0) {
System.arraycopy(b, off, buf, count, l);
count = preferredChunkSize;
flush(buf, false);
}
+
count = len - l;
/* Now write the rest of the data */
flush (b, false, l+off);
--- a/jdk/src/share/classes/sun/net/www/http/HttpClient.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/net/www/http/HttpClient.java Mon Mar 17 11:53:36 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<CookieHandler>() {
+ 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<Void>() {
+ 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<Void>() {
+ 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<java.lang.String,java.util.List<java.lang.String>>)responses.getHeaders());
+ cookieHandler.put(uri, responses.getHeaders());
}
/* decide if we're keeping alive:
--- a/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java Mon Mar 17 11:53:36 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<KeepAliveKey, ClientVector>
+ 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<Void>() {
+ 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<KeepAliveKey> keysToRemove
+ = new ArrayList<KeepAliveKey>();
- 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<KeepAliveEntry> {
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 {
--- a/jdk/src/share/classes/sun/net/www/http/KeepAliveStream.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/net/www/http/KeepAliveStream.java Mon Mar 17 11:53:36 2008 -0700
@@ -174,8 +174,8 @@
if (startCleanupThread) {
java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction() {
- public Object run() {
+ new java.security.PrivilegedAction<Void>() {
+ public Void run() {
// We want to create the Keep-Alive-SocketCleaner in the
// system threadgroup
ThreadGroup grp = Thread.currentThread().getThreadGroup();
--- a/jdk/src/share/classes/sun/net/www/http/KeepAliveStreamCleaner.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/net/www/http/KeepAliveStreamCleaner.java Mon Mar 17 11:53:36 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<Integer>() {
+ 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<Integer>() {
+ public Integer run() {
+ return NetProperties.getInteger(maxCapacityKey, MAX_CAPACITY);
+ }}).intValue();
MAX_CAPACITY = maxCapacity;
}
--- a/jdk/src/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java Mon Mar 17 11:53:36 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<ProxySelector>() {
+ public ProxySelector run() {
return ProxySelector.getDefault();
}
});
--- a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Mon Mar 17 11:53:36 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<PasswordAuthentication>() {
+ 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<CookieHandler>() {
+ 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<ResponseCache>() {
+ 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<Void>() {
+ 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<ProxySelector>() {
+ public ProxySelector run() {
return ProxySelector.getDefault();
}
});
@@ -904,9 +903,12 @@
URI uri = ParseUtil.toURI(url);
if (uri != null) {
- Map<String, List<String>> cookies = cookieHandler.get(uri, requests.getHeaders(EXCLUDE_HEADERS));
+ Map<String, List<String>> cookies
+ = cookieHandler.get(
+ uri, requests.getHeaders(EXCLUDE_HEADERS));
if (!cookies.isEmpty()) {
- for (Map.Entry<String, List<String>> entry : cookies.entrySet()) {
+ for (Map.Entry<String, List<String>> 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<IOException>() {
+ 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<InetAddress>() {
+ public InetAddress run()
throws java.net.UnknownHostException {
return InetAddress.getByName(finalHost);
}
@@ -2171,7 +2169,7 @@
* @since 1.4
*/
@Override
- public Map getHeaderFields() {
+ public Map<String, List<String>> getHeaderFields() {
try {
getInputStream();
} catch (IOException e) {}
@@ -2289,7 +2287,7 @@
* @since 1.4
*/
@Override
- public Map getRequestProperties() {
+ public Map<String, List<String>> getRequestProperties() {
if (connected)
throw new IllegalStateException("Already connected");
@@ -2375,20 +2373,15 @@
return method;
}
- private MessageHeader mapToMessageHeader(Map map) {
+ private MessageHeader mapToMessageHeader(Map<String, List<String>> 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<String, List<String>> entry : map.entrySet()) {
+ String key = entry.getKey();
+ List<String> values = entry.getValue();
+ for (String value : values) {
if (key == null) {
headers.prepend(key, value);
} else {
--- a/jdk/src/share/classes/sun/net/www/protocol/https/HttpsClient.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/net/www/protocol/https/HttpsClient.java Mon Mar 17 11:53:36 2008 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2001-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
@@ -518,6 +518,16 @@
kac.put(url, sslSocketFactory, this);
}
+ /*
+ * Close an idle connection to this URL (if it exists in the cache).
+ */
+ public void closeIdleConnection() {
+ HttpClient http = (HttpClient) kac.get(url, sslSocketFactory);
+ if (http != null) {
+ http.closeServer();
+ }
+ }
+
/**
* Returns the cipher suite in use on this connection.
*/
--- a/jdk/src/share/classes/sun/net/www/protocol/jar/URLJarFile.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/net/www/protocol/jar/URLJarFile.java Mon Mar 17 11:53:36 2008 -0700
@@ -55,7 +55,7 @@
private Manifest superMan;
private Attributes superAttr;
- private Map superEntries;
+ private Map<String, Attributes> 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<String, Attributes> 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<JarFile>() {
+ 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<String, Attributes> 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();
}
--- a/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java Mon Mar 17 11:53:36 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<FileLock> queue,
FileKey key) {
super(referent, queue);
this.fileKey = key;
@@ -1073,7 +1052,7 @@
new ConcurrentHashMap<FileKey, ArrayList<FileLockReference>>();
// reference queue for cleared refs
- private static ReferenceQueue queue = new ReferenceQueue();
+ private static ReferenceQueue<FileLock> queue = new ReferenceQueue<FileLock>();
// the enclosing file channel
private FileChannelImpl fci;
--- a/jdk/src/share/classes/sun/nio/ch/Reflect.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/nio/ch/Reflect.java Mon Mar 17 11:53:36 2008 -0700
@@ -43,8 +43,8 @@
}
private static void setAccessible(final AccessibleObject ao) {
- AccessController.doPrivileged(new PrivilegedAction() {
- public Object run() {
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ 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;
--- a/jdk/src/share/classes/sun/nio/ch/SocketAdaptor.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/nio/ch/SocketAdaptor.java Mon Mar 17 11:53:36 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<InputStream>() {
+ 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<OutputStream>() {
+ public OutputStream run() throws IOException {
return Channels.newOutputStream(sc);
}
});
--- a/jdk/src/share/classes/sun/nio/ch/Util.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/nio/ch/Util.java Mon Mar 17 11:53:36 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<SoftReference<ByteBuffer>>[] bufferPool;
static {
- bufferPool = new ThreadLocal[TEMP_BUF_POOL_SIZE];
+ bufferPool = (ThreadLocal<SoftReference<ByteBuffer>>[])
+ new ThreadLocal[TEMP_BUF_POOL_SIZE];
for (int i=0; i<TEMP_BUF_POOL_SIZE; i++)
- bufferPool[i] = new ThreadLocal();
+ bufferPool[i] = new ThreadLocal<SoftReference<ByteBuffer>>();
}
static ByteBuffer getTemporaryDirectBuffer(int size) {
ByteBuffer buf = null;
// Grab a buffer if available
for (int i=0; i<TEMP_BUF_POOL_SIZE; i++) {
- SoftReference ref = (SoftReference)(bufferPool[i].get());
- if ((ref != null) && ((buf = (ByteBuffer)ref.get()) != null) &&
+ SoftReference<ByteBuffer> 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<TEMP_BUF_POOL_SIZE; i++) {
- SoftReference ref = (SoftReference)(bufferPool[i].get());
+ SoftReference<ByteBuffer> ref = bufferPool[i].get();
if ((ref == null) || (ref.get() == null)) {
- bufferPool[i].set(new SoftReference(buf));
+ bufferPool[i].set(new SoftReference<ByteBuffer>(buf));
return;
}
}
// Otherwise replace a smaller one in the cache if such exists
for (int i=0; i<TEMP_BUF_POOL_SIZE; i++) {
- SoftReference ref = (SoftReference)(bufferPool[i].get());
- ByteBuffer inCacheBuf = (ByteBuffer)ref.get();
+ SoftReference<ByteBuffer> 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<ByteBuffer>(buf));
return;
}
}
@@ -120,10 +121,12 @@
}
// Per-thread cached selector
- private static ThreadLocal localSelector = new ThreadLocal();
+ private static ThreadLocal<SoftReference<SelectorWrapper>> localSelector
+ = new ThreadLocal<SoftReference<SelectorWrapper>>();
// 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<SelectorWrapper> localSelectorWrapper
+ = new ThreadLocal<SelectorWrapper>();
// 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<SelectorWrapper> 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<SelectorWrapper>(
+ 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<Void>() {
+ 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<Void>() {
+ 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,
--- a/jdk/src/share/classes/sun/reflect/ClassDefiner.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/reflect/ClassDefiner.java Mon Mar 17 11:53:36 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<ClassLoader>() {
+ public ClassLoader run() {
return new DelegatingClassLoader(parentClassLoader);
}
});
--- a/jdk/src/share/classes/sun/reflect/MethodAccessorGenerator.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/reflect/MethodAccessorGenerator.java Mon Mar 17 11:53:36 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<MagicAccessorImpl>() {
+ public MagicAccessorImpl run() {
try {
- return ClassDefiner.defineClass
+ return (MagicAccessorImpl)
+ ClassDefiner.defineClass
(generatedName,
bytes,
0,
--- a/jdk/src/share/classes/sun/reflect/ReflectionFactory.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/reflect/ReflectionFactory.java Mon Mar 17 11:53:36 2008 -0700
@@ -84,8 +84,8 @@
* <code>AccessController.doPrivileged</code>.
*/
public static final class GetReflectionFactoryAction
- implements PrivilegedAction {
- public Object run() {
+ implements PrivilegedAction<ReflectionFactory> {
+ 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 <T> Constructor<T> copyConstructor(Constructor<T> 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<Void>() {
+ 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
--- a/jdk/src/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java Mon Mar 17 11:53:36 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<Void>() {
+ public Void run() {
AccessibleObject.setAccessible(mm, true);
return null;
}
--- a/jdk/src/share/classes/sun/reflect/misc/MethodUtil.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/reflect/misc/MethodUtil.java Mon Mar 17 11:53:36 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<Signature, Method> sigs = new HashMap<Signature, Method>();
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<Signature, Method> 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<Signature, Method> sigs) {
Method[] methods = null;
try {
/*
@@ -178,7 +179,7 @@
return done;
}
- private static void addMethod(Map sigs, Method method) {
+ private static void addMethod(Map<Signature, Method> 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<Method>() {
+ 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;
}
--- a/jdk/src/share/classes/sun/rmi/log/ReliableLog.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/rmi/log/ReliableLog.java Mon Mar 17 11:53:36 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<? extends LogFile>
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 =
--- a/jdk/src/share/classes/sun/rmi/registry/RegistryImpl.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/rmi/registry/RegistryImpl.java Mon Mar 17 11:53:36 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<String, Remote> bindings
+ = new Hashtable<String, Remote>(101);
+ private static Hashtable<InetAddress, InetAddress> allowedAccessCache
+ = new Hashtable<InetAddress, InetAddress>(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<InetAddress>() {
+ 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<Void>() {
+ public Void run() throws java.io.IOException {
/*
* if a ServerSocket can be bound to the client's
* address then that address must be local
--- a/jdk/src/share/classes/sun/rmi/rmic/RemoteClass.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/rmi/rmic/RemoteClass.java Mon Mar 17 11:53:36 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<ClassDefinition> remotesImplemented = // list of remote interfaces found
+ new Vector<ClassDefinition>();
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<String, Method> methods = new Hashtable<String, Method>();
boolean errors = false;
- for (Enumeration enumeration = remotesImplemented.elements();
+ for (Enumeration<ClassDefinition> 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<Method> 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]);
/***** <DEBUG> */
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<String, Method> 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<ClassDeclaration> legalExceptions
+ = new Vector<ClassDeclaration>();
try {
collectCompatibleExceptions(
other.exceptions, exceptions, legalExceptions);
@@ -814,7 +815,7 @@
*/
private void collectCompatibleExceptions(ClassDeclaration[] from,
ClassDeclaration[] with,
- Vector list)
+ Vector<ClassDeclaration> list)
throws ClassNotFound
{
for (int i = 0; i < from.length; i++) {
--- a/jdk/src/share/classes/sun/rmi/rmic/newrmic/jrmp/RemoteClass.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/rmi/rmic/newrmic/jrmp/RemoteClass.java Mon Mar 17 11:53:36 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();
}
/**
--- a/jdk/src/share/classes/sun/rmi/runtime/Log.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/rmi/runtime/Log.java Mon Mar 17 11:53:36 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<Handler>() {
+ 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<Void>() {
+ public Void run() {
if (!logger.isLoggable(level)) {
logger.setLevel(level);
}
--- a/jdk/src/share/classes/sun/rmi/server/LoaderHandler.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/rmi/server/LoaderHandler.java Mon Mar 17 11:53:36 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<ClassLoader, Void> codebaseLoaders =
+ Collections.synchronizedMap(new IdentityHashMap<ClassLoader, Void>(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<LoaderKey, LoaderEntry> loaderTable
+ = new HashMap<LoaderKey, LoaderEntry>(5);
/** reference queue for cleared class loader entries */
- private static final ReferenceQueue refQueue = new ReferenceQueue();
+ private static final ReferenceQueue<Loader> refQueue
+ = new ReferenceQueue<Loader>();
/*
* 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<String>(path)});
}
return urls;
}
/** map from weak(key=string) to [URL[], soft(key)] */
- private static final Map pathToURLsCache = new WeakHashMap(5);
+ private static final Map<String, Object[]> pathToURLsCache
+ = new WeakHashMap<String, Object[]>(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<Loader>() {
+ 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<Loader> {
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<PermissionCollection>() {
+ public PermissionCollection run() {
CodeSource codesource = new CodeSource(null,
(java.security.cert.Certificate[]) null);
Policy p = java.security.Policy.getPolicy();
--- a/jdk/src/share/classes/sun/rmi/server/MarshalInputStream.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/rmi/server/MarshalInputStream.java Mon Mar 17 11:53:36 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<String, Class<?>> permittedSunClasses
+ = new HashMap<String, Class<?>>(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<Object, Runnable> doneCallbacks
+ = new HashMap<Object, Runnable>(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<Runnable> 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) ||
--- a/jdk/src/share/classes/sun/rmi/server/MarshalOutputStream.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/rmi/server/MarshalOutputStream.java Mon Mar 17 11:53:36 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<Void>() {
+ public Void run() {
enableReplaceObject(true);
return null;
}
--- a/jdk/src/share/classes/sun/rmi/server/Util.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/rmi/server/Util.java Mon Mar 17 11:53:36 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<Class<?>, Void> withoutStubs =
+ Collections.synchronizedMap(new WeakHashMap<Class<?>, 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<Class<?>> list = new ArrayList<Class<?>>();
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<Class<?>> 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 });
--- a/jdk/src/share/classes/sun/rmi/server/WeakClassHashMap.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/rmi/server/WeakClassHashMap.java Mon Mar 17 11:53:36 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);
--- a/jdk/src/share/classes/sun/rmi/transport/DGCClient.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/rmi/transport/DGCClient.java Mon Mar 17 11:53:36 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<Void>() {
+ public Void run() {
renewCleanThread.interrupt();
return null;
}
--- a/jdk/src/share/classes/sun/rmi/transport/Target.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/rmi/transport/Target.java Mon Mar 17 11:53:36 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<Void>() {
+ public Void run() {
t.setContextClassLoader(ccl);
return null;
}
--- a/jdk/src/share/classes/sun/rmi/transport/Transport.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/rmi/transport/Transport.java Mon Mar 17 11:53:36 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<Void>() {
+ public Void run() throws IOException {
checkAcceptPermission(acc);
disp.dispatch(impl, call);
return null;
--- a/jdk/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java Mon Mar 17 11:53:36 2008 -0700
@@ -89,8 +89,8 @@
static {
java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction() {
- public Object run() {
+ new java.security.PrivilegedAction<Void>() {
+ public Void run() {
ContentLength =
Integer.getInteger("CONTENT_LENGTH", 0).intValue();
QueryString = System.getProperty("QUERY_STRING", "");
--- a/jdk/src/share/classes/sun/rmi/transport/proxy/HttpSendSocket.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/rmi/transport/proxy/HttpSendSocket.java Mon Mar 17 11:53:36 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"));
/**
--- a/jdk/src/share/classes/sun/rmi/transport/proxy/RMIMasterSocketFactory.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/rmi/transport/proxy/RMIMasterSocketFactory.java Mon Mar 17 11:53:36 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 {
--- a/jdk/src/share/classes/sun/rmi/transport/tcp/ConnectionMultiplexer.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/rmi/transport/tcp/ConnectionMultiplexer.java Mon Mar 17 11:53:36 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"));
}
--- a/jdk/src/share/classes/sun/security/jgss/GSSManagerImpl.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/GSSManagerImpl.java Mon Mar 17 11:53:36 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){
--- a/jdk/src/share/classes/sun/security/jgss/krb5/InitSecContextToken.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/InitSecContextToken.java Mon Mar 17 11:53:36 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: " +
--- a/jdk/src/share/classes/sun/security/krb5/Config.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/Config.java Mon Mar 17 11:53:36 2008 -0700
@@ -1040,11 +1040,12 @@
* Check if need to use DNS to locate Kerberos services
*/
public boolean useDNS(String name) {
- boolean value = getDefaultBooleanValue(name, "libdefaults");
- if (value == false) {
- value = getDefaultBooleanValue("dns_fallback", "libdefaults");
+ String value = getDefault(name, "libdefaults");
+ if (value == null) {
+ return getDefaultBooleanValue("dns_fallback", "libdefaults");
+ } else {
+ return value.equalsIgnoreCase("true");
}
- return value;
}
/**
--- a/jdk/src/share/classes/sun/security/ssl/CipherSuite.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/CipherSuite.java Mon Mar 17 11:53:36 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
--- a/jdk/src/share/classes/sun/security/ssl/DHCrypt.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/DHCrypt.java Mon Mar 17 11:53:36 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);
}
--- a/jdk/src/share/classes/sun/security/ssl/Handshaker.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/Handshaker.java Mon Mar 17 11:53:36 2008 -0700
@@ -617,7 +617,8 @@
r.write(1); // single byte of data
if (conn != null) {
- synchronized (conn.writeLock) {
+ conn.writeLock.lock();
+ try {
conn.writeRecord(r);
conn.changeWriteCiphers();
if (debug != null && Debug.isOn("handshake")) {
@@ -625,6 +626,8 @@
}
mesg.write(output);
output.flush();
+ } finally {
+ conn.writeLock.unlock();
}
} else {
synchronized (engine.writeLock) {
--- a/jdk/src/share/classes/sun/security/ssl/InputRecord.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/InputRecord.java Mon Mar 17 11:53:36 2008 -0700
@@ -426,11 +426,11 @@
if (really < 0) {
throw new SSLException("SSL peer shut down incorrectly");
}
+ }
- // now we've got a complete record.
- count = contentLen + headerSize;
- exlen = 0;
- }
+ // now we've got a complete record.
+ count = contentLen + headerSize;
+ exlen = 0;
if (debug != null && Debug.isOn("record")) {
if (count < 0 || count > (maxRecordSize - headerSize)) {
@@ -502,10 +502,11 @@
if (really < 0) {
throw new EOFException("SSL peer shut down incorrectly");
}
+ }
- // now we've got a complete record.
- exlen = 0;
- }
+ // now we've got a complete record.
+ exlen = 0;
+
hashInternal(buf, 2, 3);
hashInternal(v2Buf, 0, len);
V2toV3ClientHello(v2Buf);
--- a/jdk/src/share/classes/sun/security/ssl/JsseJce.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/JsseJce.java Mon Mar 17 11:53:36 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);
}
--- a/jdk/src/share/classes/sun/security/ssl/OutputRecord.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/OutputRecord.java Mon Mar 17 11:53:36 2008 -0700
@@ -174,6 +174,18 @@
return count == headerSize;
}
+ /*
+ * Return true if the record is of a given alert.
+ */
+ boolean isAlert(byte description) {
+ // An alert is defined with a two bytes struct,
+ // {byte level, byte description}, following after the header bytes.
+ if (count > (headerSize + 1) && contentType == ct_alert) {
+ return buf[headerSize + 1] == description;
+ }
+
+ return false;
+ }
/*
* Compute the MAC and append it to this record. In case we
--- a/jdk/src/share/classes/sun/security/ssl/ProtocolList.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/ProtocolList.java Mon Mar 17 11:53:36 2008 -0700
@@ -98,7 +98,7 @@
protocolNames[i++] = version.name;
}
}
- return (String[])protocolNames.clone();
+ return protocolNames.clone();
}
public String toString() {
--- a/jdk/src/share/classes/sun/security/ssl/SSLSessionImpl.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/SSLSessionImpl.java Mon Mar 17 11:53:36 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());
}
/**
--- a/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java Mon Mar 17 11:53:36 2008 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,8 @@
import java.security.AccessControlContext;
import java.security.PrivilegedAction;
import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReentrantLock;
import javax.crypto.BadPaddingException;
@@ -274,7 +276,7 @@
* from the peer are handled properly.
*/
private Object handshakeLock;
- Object writeLock;
+ ReentrantLock writeLock;
private Object readLock;
private InputRecord inrec;
@@ -314,7 +316,6 @@
private HashMap<HandshakeCompletedListener, AccessControlContext>
handshakeListeners;
-
/*
* Reuse the same internal input/output streams.
*/
@@ -526,7 +527,7 @@
enabledCipherSuites = CipherSuiteList.getDefault();
enabledProtocols = ProtocolList.getDefault();
handshakeLock = new Object();
- writeLock = new Object();
+ writeLock = new ReentrantLock();
readLock = new Object();
inrec = null;
@@ -677,16 +678,81 @@
// implementations are fragile and don't like to see empty
// records, so this also increases robustness.
//
- synchronized (writeLock) {
- if (!r.isEmpty()) {
- // r.compress(c);
- r.addMAC(writeMAC);
- r.encrypt(writeCipher);
- r.write(sockOutput);
+ if (!r.isEmpty()) {
+
+ // If the record is a close notify alert, we need to honor
+ // socket option SO_LINGER. Note that we will try to send
+ // the close notify even if the SO_LINGER set to zero.
+ if (r.isAlert(Alerts.alert_close_notify) && getSoLinger() >= 0) {
+
+ // keep and clear the current thread interruption status.
+ boolean interrupted = Thread.interrupted();
+ try {
+ if (writeLock.tryLock(getSoLinger(), TimeUnit.SECONDS)) {
+ try {
+ writeRecordInternal(r);
+ } finally {
+ writeLock.unlock();
+ }
+ } else {
+ SSLException ssle = new SSLException(
+ "SO_LINGER timeout," +
+ " close_notify message cannot be sent.");
+
+
+ // For layered, non-autoclose sockets, we are not
+ // able to bring them into a usable state, so we
+ // treat it as fatal error.
+ if (self != this && !autoClose) {
+ // Note that the alert description is
+ // specified as -1, so no message will be send
+ // to peer anymore.
+ fatal((byte)(-1), ssle);
+ } else if ((debug != null) && Debug.isOn("ssl")) {
+ System.out.println(threadName() +
+ ", received Exception: " + ssle);
+ }
+
+ // RFC2246 requires that the session becomes
+ // unresumable if any connection is terminated
+ // without proper close_notify messages with
+ // level equal to warning.
+ //
+ // RFC4346 no longer requires that a session not be
+ // resumed if failure to properly close a connection.
+ //
+ // We choose to make the session unresumable if
+ // failed to send the close_notify message.
+ //
+ sess.invalidate();
+ }
+ } catch (InterruptedException ie) {
+ // keep interrupted status
+ interrupted = true;
+ }
+
+ // restore the interrupted status
+ if (interrupted) {
+ Thread.currentThread().interrupt();
+ }
+ } else {
+ writeLock.lock();
+ try {
+ writeRecordInternal(r);
+ } finally {
+ writeLock.unlock();
+ }
}
}
}
+ private void writeRecordInternal(OutputRecord r) throws IOException {
+ // r.compress(c);
+ r.addMAC(writeMAC);
+ r.encrypt(writeCipher);
+ r.write(sockOutput);
+ }
+
/*
* Read an application data record. Alerts and handshake
@@ -1533,7 +1599,11 @@
if (oldState == cs_HANDSHAKE) {
sockInput.skip(sockInput.available());
}
- sendAlert(Alerts.alert_fatal, description);
+
+ // If the description equals -1, the alert won't be sent to peer.
+ if (description != -1) {
+ sendAlert(Alerts.alert_fatal, description);
+ }
if (cause instanceof SSLException) { // only true if != null
closeReason = (SSLException)cause;
} else {
@@ -1614,7 +1684,7 @@
* Emit alerts. Caller must have synchronized with "this".
*/
private void sendAlert(byte level, byte description) {
- if (connectionState >= cs_CLOSED) {
+ if (connectionState >= cs_SENT_CLOSE) {
return;
}
--- a/jdk/src/share/classes/sun/security/ssl/SessionId.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/SessionId.java Mon Mar 17 11:53:36 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 */
--- a/jdk/src/share/classes/sun/security/ssl/SunX509KeyManagerImpl.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/SunX509KeyManagerImpl.java Mon Mar 17 11:53:36 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);
}
--- a/jdk/src/share/classes/sun/security/x509/AVA.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/security/x509/AVA.java Mon Mar 17 11:53:36 2008 -0700
@@ -780,7 +780,8 @@
* Implementations MAY escape other characters.
*
* NOTE: this implementation also recognizes "=" and "#" as
- * characters which need escaping.
+ * characters which need escaping, and null which is escaped as
+ * '\00' (see RFC 4514).
*
* If a character to be escaped is one of the list shown above, then
* it is prefixed by a backslash ('\' ASCII 92).
@@ -805,6 +806,10 @@
// append printable/escaped char
sbuffer.append(c);
+ } else if (c == '\u0000') {
+ // escape null character
+ sbuffer.append("\\00");
+
} else if (debug != null && Debug.isOn("ava")) {
// embed non-printable/non-escaped char
--- a/jdk/src/share/classes/sun/security/x509/CertificatePolicySet.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/security/x509/CertificatePolicySet.java Mon Mar 17 11:53:36 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);
}
--- a/jdk/src/share/classes/sun/security/x509/X509Cert.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/security/x509/X509Cert.java Mon Mar 17 11:53:36 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(); }
/**
--- a/jdk/src/share/classes/sun/tools/jar/JarVerifierStream.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/tools/jar/JarVerifierStream.java Mon Mar 17 11:53:36 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<String, Vector<SystemIdentity>> verified
+ = new Hashtable<String, Vector<SystemIdentity>>();
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<SystemIdentity> ids = getIds(certs);
if (ids != null) {
verified.put(current.getName(), ids);
}
@@ -189,7 +189,7 @@
static class CertCache {
Certificate [] certs;
- Vector ids;
+ Vector<SystemIdentity> ids;
boolean equals(Certificate[] certs) {
if (this.certs == null) {
@@ -229,21 +229,21 @@
}
}
- private ArrayList certCache = null;
+ private ArrayList<CertCache> certCache = null;
/**
* Returns the Identity vector for the given array of Certificates
*/
- protected Vector getIds(Certificate[] certs) {
+ protected Vector<SystemIdentity> getIds(Certificate[] certs) {
if (certs == null)
return null;
if (certCache == null)
- certCache = new ArrayList();
+ certCache = new ArrayList<CertCache>();
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<Void>() {
+ 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<SystemIdentity>();
cc.ids.addElement(id);
} catch (java.security.KeyManagementException kme) {
// ignore if we can't create Identity
--- a/jdk/src/share/classes/sun/tools/jconsole/MBeansTab.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/tools/jconsole/MBeansTab.java Mon Mar 17 11:53:36 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<Set<ObjectName>, Void>() {
+ @Override
+ public Set<ObjectName> 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<ObjectName> 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<ObjectName> 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<ObjectName> 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 {
+ }
}
--- a/jdk/src/share/classes/sun/tools/jconsole/MemoryPoolStat.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/tools/jconsole/MemoryPoolStat.java Mon Mar 17 11:53:36 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;
--- a/jdk/src/share/classes/sun/tools/jconsole/VMPanel.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/tools/jconsole/VMPanel.java Mon Mar 17 11:53:36 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<TabInfo> tabInfos = new ArrayList<TabInfo>();
-
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<JConsolePlugin, SwingWorker<?,?>> plugins = null;
+ private Map<JConsolePlugin, SwingWorker<?, ?>> 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<JConsolePlugin, SwingWorker<?,?>>();
+ plugins = new LinkedHashMap<JConsolePlugin, SwingWorker<?, ?>>();
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 = {
"<html><h3>" + getText("connectingTo1", connectionName) + "</h3></html>",
progressPanel,
- "<html><b>" + getText("connectingTo2", connectionName) + "</b></html>"
+ "<html><b>" + getText("connectingTo2", connectionName) + "</b></html>"
};
-
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,
- "<html><h3>" + msgTitle + "</h3>" +
- "<b>" + msgExplanation + "</b>",
- JOptionPane.DEFAULT_OPTION,
- JOptionPane.WARNING_MESSAGE, null,
- new String[] { buttonStr, cancelStr },
- 0);
+ SheetDialog.showOptionDialog(this,
+ "<html><h3>" + msgTitle + "</h3>" +
+ "<b>" + msgExplanation + "</b>",
+ 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<? extends Tab> tabClass;
String name;
boolean tabVisible;
--- a/jdk/src/share/classes/sun/tools/jconsole/inspector/OperationEntry.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/OperationEntry.java Mon Mar 17 11:53:36 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.*;
--- a/jdk/src/share/classes/sun/tools/jconsole/inspector/TableSorter.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/TableSorter.java Mon Mar 17 11:53:36 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.*;
--- a/jdk/src/share/classes/sun/tools/jconsole/inspector/ThreadDialog.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/ThreadDialog.java Mon Mar 17 11:53:36 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
--- a/jdk/src/share/classes/sun/tools/jconsole/inspector/Utils.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/Utils.java Mon Mar 17 11:53:36 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<Integer> tableNavigationKeys =
- new HashSet<Integer>(Arrays.asList(new Integer[] {
+ new HashSet<Integer>(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<Class<?>> primitiveWrappers =
- new HashSet<Class<?>>(Arrays.asList(new Class<?>[] {
+ new HashSet<Class<?>>(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<Class<?>> primitives = new HashSet<Class<?>>();
-
private static final Map<String, Class<?>> primitiveMap =
new HashMap<String, Class<?>>();
-
private static final Map<String, Class<?>> primitiveToWrapper =
new HashMap<String, Class<?>>();
-
private static final Set<String> editableTypes = new HashSet<String>();
-
private static final Set<Class<?>> extraEditableClasses =
- new HashSet<Class<?>>(Arrays.asList(new Class<?>[] {
+ new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{
BigDecimal.class, BigInteger.class, Number.class,
- String.class, ObjectName.class}));
-
+ String.class, ObjectName.class
+ }));
private static final Set<String> numericalTypes = new HashSet<String>();
-
private static final Set<String> extraNumericalTypes =
- new HashSet<String>(Arrays.asList(new String[] {
+ new HashSet<String>(Arrays.asList(new String[]{
BigDecimal.class.getName(), BigInteger.class.getName(),
- Number.class.getName()}));
-
+ Number.class.getName()
+ }));
private static final Set<String> booleanTypes =
- new HashSet<String>(Arrays.asList(new String[] {
- Boolean.TYPE.getName(), Boolean.class.getName()}));
+ new HashSet<String>(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();
}
--- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XDataViewer.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XDataViewer.java Mon Mar 17 11:53:36 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);
}
--- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XMBean.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XMBean.java Mon Mar 17 11:53:36 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();
}
--- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XMBeanInfo.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XMBeanInfo.java Mon Mar 17 11:53:36 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);
- }
- }
- }
- }
}
--- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XMBeanNotifications.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XMBeanNotifications.java Mon Mar 17 11:53:36 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<ObjectName, XMBeanNotificationsListener> listeners =
- new HashMap<ObjectName, XMBeanNotificationsListener>();
- private boolean subscribed;
+ new HashMap<ObjectName, XMBeanNotificationsListener>();
+ private volatile boolean subscribed;
private XMBeanNotificationsListener currentListener;
public final static String NOTIFICATION_RECEIVED_EVENT =
- "jconsole.xnotification.received";
-
+ "jconsole.xnotification.received";
private List<NotificationListener> 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<NotificationListener> l =
- new ArrayList<NotificationListener>(1);
+ new ArrayList<NotificationListener>(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<Object[]> 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<Object[]> 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<Object[]> data = new ArrayList<Object[]>();
- 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();
+ }
+ }
+ }
+ }
+ });
}
}
}
--- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XMBeanOperations.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XMBeanOperations.java Mon Mar 17 11:53:36 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.*;
--- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XObject.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XObject.java Mon Mar 17 11:53:36 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
--- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XOperations.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XOperations.java Mon Mar 17 11:53:36 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<NotificationListener> notificationListenersList;
-
private Hashtable<JButton, OperationEntry> 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<JButton, OperationEntry>();
ArrayList<NotificationListener> l =
- new ArrayList<NotificationListener>(1);
+ new ArrayList<NotificationListener>(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;i<operations.length;i++) {
- innerPanelLeft = new JPanel(new FlowLayout(FlowLayout.RIGHT));
+ for (int i = 0; i < operations.length; i++) {
+ innerPanelLeft = new JPanel(new FlowLayout(FlowLayout.RIGHT));
innerPanelRight = new JPanel(new FlowLayout(FlowLayout.LEFT));
- innerPanelLeft.add(methodLabel =
- new JLabel(Utils.
- getReadableClassName(operations[i].
- getReturnType()),
- JLabel.RIGHT));
- if (methodLabel.getText().length()>20) {
+ 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<Object, Void>() {
+ @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);
}
--- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XPlotter.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XPlotter.java Mon Mar 17 11:53:36 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;
--- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XPlottingViewer.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XPlottingViewer.java Mon Mar 17 11:53:36 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.*;
--- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XSheet.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XSheet.java Mon Mar 17 11:53:36 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<MBeanInfo, Void> sw = new SwingWorker<MBeanInfo, Void>() {
+ @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<MBeanAttributeInfo, Void> sw =
+ new SwingWorker<MBeanAttributeInfo, Void>() {
+ @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<Void, Void> sw = new SwingWorker<Void, Void>() {
+ @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<MBeanInfo, Void> sw = new SwingWorker<MBeanInfo, Void>() {
+ @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<Void, Void>() {
+ @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<Boolean, Void>() {
+ @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 = "<html><b>" + text + "</b></html>";
}
@@ -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<Void, Void>() {
+ @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;
}
}
--- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XTable.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XTable.java Mon Mar 17 11:53:36 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.*;
--- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XTextField.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XTextField.java Mon Mar 17 11:53:36 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.*;
--- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XTextFieldEditor.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XTextFieldEditor.java Mon Mar 17 11:53:36 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;
--- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XTree.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XTree.java Mon Mar 17 11:53:36 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<String> orderedKeyPropertyList =
new ArrayList<String>();
+
static {
String keyPropertyList =
System.getProperty("com.sun.tools.jconsole.mbeans.keyPropertyList");
@@ -54,9 +55,7 @@
}
}
}
-
private MBeansTab mbeansTab;
-
private Map<String, DefaultMutableTreeNode> nodes =
new HashMap<String, DefaultMutableTreeNode>();
@@ -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<DefaultMutableTreeNode> metadataNodes =
new HashSet<DefaultMutableTreeNode>();
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<ObjectName> mbeans) {
+ Set<Dn> dns = new TreeSet<Dn>();
+ 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<String,String> extractKeyValuePairs(
- String properties, ObjectName mbean) {
- String props = properties;
- Map<String,String> map = new LinkedHashMap<String,String>();
+ private static Map<String, String> extractKeyValuePairs(
+ String props, ObjectName mbean) {
+ Map<String, String> map = new LinkedHashMap<String, String>();
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<String,String> map = extractKeyValuePairs(props, mbean);
+ Map<String, String> 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<String,String> entry : map.entrySet()) {
+ for (Map.Entry<String, String> 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<String,String> map = extractKeyValuePairs(props, mbean);
- for (Map.Entry<String,String> 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<DefaultMutableTreeNode> {
- 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<Object[], Void> {
+
+ 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<DefaultMutableTreeNode> {
- public static class Dn {
+ public int compareTo(DefaultMutableTreeNode node) {
+ return (this.toString().compareTo(node.toString()));
+ }
+ }
+ private static class Dn implements Comparable<Dn> {
+
+ private ObjectName mbean;
private String domain;
- private String dn;
+ private String keyPropertyList;
private String hashDn;
- private ArrayList<Token> tokens = new ArrayList<Token>();
+ private List<Token> tokens = new ArrayList<Token>();
+
+ 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<String, String> map =
+ extractKeyValuePairs(keyPropertyList, mbean);
+ for (Map.Entry<String, String> 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<Token> newOrder = new ArrayList<Token>(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());
}
}
}
--- a/jdk/src/share/classes/sun/tools/native2ascii/N2AFilter.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/classes/sun/tools/native2ascii/N2AFilter.java Mon Mar 17 11:53:36 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);
}
--- a/jdk/src/share/native/java/io/io_util.c Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/share/native/java/io/io_util.c Mon Mar 17 11:53:36 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) {
--- a/jdk/src/solaris/bin/java_md.c Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/solaris/bin/java_md.c Mon Mar 17 11:53:36 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();
+}
--- a/jdk/src/solaris/classes/java/io/FileDescriptor.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/solaris/classes/java/io/FileDescriptor.java Mon Mar 17 11:53:36 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();
--- a/jdk/src/solaris/classes/java/lang/ProcessImpl.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/solaris/classes/java/lang/ProcessImpl.java Mon Mar 17 11:53:36 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<String,String> 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(); }
+ }
+ }
}
}
--- a/jdk/src/solaris/classes/java/lang/UNIXProcess.java.linux Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/solaris/classes/java/lang/UNIXProcess.java.linux Mon Mar 17 11:53:36 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 <em>not</em> -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<Void>() {
+ 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<Void>() {
+ 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();
}
}
--- a/jdk/src/solaris/classes/java/lang/UNIXProcess.java.solaris Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/solaris/classes/java/lang/UNIXProcess.java.solaris Mon Mar 17 11:53:36 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 <em>not</em> -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<Void>() { 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<Void>() { 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();
}
}
--- a/jdk/src/solaris/classes/java/net/PlainSocketImpl.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/solaris/classes/java/net/PlainSocketImpl.java Mon Mar 17 11:53:36 2008 -0700
@@ -76,9 +76,6 @@
native int socketGetOption(int opt, Object iaContainerObj) throws SocketException;
- native int socketGetOption1(int opt, Object iaContainerObj, FileDescriptor fd)
- throws SocketException;
-
native void socketSendUrgentData(int data) throws IOException;
}
--- a/jdk/src/solaris/classes/java/util/prefs/FileSystemPreferences.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/solaris/classes/java/util/prefs/FileSystemPreferences.java Mon Mar 17 11:53:36 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<Void>() {
+ 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<Void>() {
+ 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<String, String> 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<Change> changeLog = new ArrayList<Change>();
/**
* Represents a change to a preference.
@@ -424,7 +420,7 @@
*/
private void replayChanges() {
for (int i = 0, n = changeLog.size(); i<n; i++)
- ((Change)changeLog.get(i)).replay();
+ changeLog.get(i).replay();
}
private static Timer syncTimer = new Timer(true); // Daemon Thread
@@ -438,8 +434,8 @@
}, SYNC_INTERVAL*1000, SYNC_INTERVAL*1000);
// Add shutdown hook to flush cached prefs on normal termination
- AccessController.doPrivileged(new PrivilegedAction() {
- public Object run() {
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ 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<Void>() {
+ 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<String, String>();
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<String, String>();
}
}
@@ -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<Void>() {
+ public Void run() throws BackingStoreException {
+ Map<String, String> m = new TreeMap<String, String>();
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<String, String>();
} 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<Void>() {
+ 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<String[]>() {
+ public String[] run() {
+ List<String> result = new ArrayList<String>();
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<Void>() {
+ 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<Long>() {
+ 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<Void>() {
+ 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<Void>() {
+ 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<String, String>();
replayChanges();
}
if (!changeLog.isEmpty()) {
--- a/jdk/src/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java Mon Mar 17 11:53:36 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) {
--- a/jdk/src/solaris/classes/sun/security/provider/NativePRNG.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/solaris/classes/sun/security/provider/NativePRNG.java Mon Mar 17 11:53:36 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<RandomIO>() {
+ 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
--- a/jdk/src/solaris/native/java/io/FileOutputStream_md.c Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/solaris/native/java/io/FileOutputStream_md.c Mon Mar 17 11:53:36 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
--- a/jdk/src/solaris/native/java/lang/UNIXProcess_md.c Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/solaris/native/java/lang/UNIXProcess_md.c Mon Mar 17 11:53:36 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:
--- a/jdk/src/windows/bin/java_md.c Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/windows/bin/java_md.c Mon Mar 17 11:53:36 2008 -0700
@@ -33,6 +33,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <wtypes.h>
+#include <commctrl.h>
#include <jni.h>
#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();
+}
--- a/jdk/src/windows/classes/java/io/FileDescriptor.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/windows/classes/java/io/FileDescriptor.java Mon Mar 17 11:53:36 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
- * <code>FileInputStream</code> or <code>FileOutputStream</code> to
- * contain it.
- * <p>
- * 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.
+ *
+ * <p>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 <code>System.in</code>.
+ * 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 <code>System.out</code>.
+ * 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 <code>System.err</code>.
+ * known as {@code System.err}.
*
* @see java.lang.System#err
*/
@@ -114,9 +119,9 @@
/**
* Tests if this file descriptor object is valid.
*
- * @return <code>true</code> 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;
- * <code>false</code> otherwise.
+ * {@code false} otherwise.
*/
public boolean valid() {
return ((handle != -1) || (fd != -1));
--- a/jdk/src/windows/classes/java/lang/ProcessImpl.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/windows/classes/java/lang/ProcessImpl.java Mon Mar 17 11:53:36 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<String,String> 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<Void>() {
+ 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 <em>not</em> -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);
--- a/jdk/src/windows/classes/java/net/DualStackPlainSocketImpl.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/windows/classes/java/net/DualStackPlainSocketImpl.java Mon Mar 17 11:53:36 2008 -0700
@@ -218,9 +218,6 @@
return value;
}
- int socketGetOption1(int opt, Object iaContainerObj, FileDescriptor fd)
- throws SocketException {return 0;} // un-implemented REMOVE
-
void socketSendUrgentData(int data) throws IOException {
int nativefd = checkAndReturnNativeFD();
sendOOB(nativefd, data);
--- a/jdk/src/windows/classes/java/net/PlainSocketImpl.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/windows/classes/java/net/PlainSocketImpl.java Mon Mar 17 11:53:36 2008 -0700
@@ -304,11 +304,6 @@
return impl.socketGetOption(opt, iaContainerObj);
}
- int socketGetOption1(int opt, Object iaContainerObj, FileDescriptor fd)
- throws SocketException {
- return impl.socketGetOption1(opt, iaContainerObj, fd);
- }
-
void socketSendUrgentData(int data) throws IOException {
impl.socketSendUrgentData(data);
}
--- a/jdk/src/windows/classes/java/net/TwoStacksPlainSocketImpl.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/windows/classes/java/net/TwoStacksPlainSocketImpl.java Mon Mar 17 11:53:36 2008 -0700
@@ -199,8 +199,5 @@
native int socketGetOption(int opt, Object iaContainerObj) throws SocketException;
- native int socketGetOption1(int opt, Object iaContainerObj, FileDescriptor fd)
- throws SocketException;
-
native void socketSendUrgentData(int data) throws IOException;
}
--- a/jdk/src/windows/classes/sun/security/mscapi/SunMSCAPI.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/windows/classes/sun/security/mscapi/SunMSCAPI.java Mon Mar 17 11:53:36 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<Void>() {
+ public Void run() {
System.loadLibrary("sunmscapi");
return null;
}
--- a/jdk/src/windows/native/java/io/FileOutputStream_md.c Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/windows/native/java/io/FileOutputStream_md.c Mon Mar 17 11:53:36 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);
}
--- a/jdk/src/windows/native/java/io/io_util_md.c Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/windows/native/java/io/io_util_md.c Mon Mar 17 11:53:36 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;
}
--- a/jdk/src/windows/native/java/io/io_util_md.h Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/windows/native/java/io/io_util_md.h Mon Mar 17 11:53:36 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);
--- a/jdk/src/windows/native/java/lang/ProcessImpl_md.c Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/windows/native/java/lang/ProcessImpl_md.c Mon Mar 17 11:53:36 2008 -0700
@@ -33,7 +33,12 @@
#include <windows.h>
#include <io.h>
-#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:
--- a/jdk/src/windows/native/java/lang/java_props_md.c Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/windows/native/java/lang/java_props_md.c Mon Mar 17 11:53:36 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)";
}
--- a/jdk/src/windows/native/sun/net/www/protocol/http/NTLMAuthSequence.c Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/src/windows/native/sun/net/www/protocol/http/NTLMAuthSequence.c Mon Mar 17 11:53:36 2008 -0700
@@ -36,6 +36,8 @@
#include <tchar.h>
#include <fcntl.h>
+#include "jni_util.h"
+
#define SECURITY_WIN32
#include "sspi.h"
#include "issperr.h"
@@ -117,22 +119,36 @@
{
SEC_WINNT_AUTH_IDENTITY AuthId;
SEC_WINNT_AUTH_IDENTITY * pAuthId;
- CHAR *pUser = 0;
- CHAR *pDomain = 0;
- CHAR *pPassword = 0;
+ const CHAR *pUser = 0;
+ const CHAR *pDomain = 0;
+ const CHAR *pPassword = 0;
CredHandle *pCred;
TimeStamp ltime;
jboolean isCopy;
SECURITY_STATUS ss;
if (user != 0) {
- pUser = (CHAR *)(*env)->GetStringUTFChars(env, user, &isCopy);
+ pUser = JNU_GetStringPlatformChars(env, user, &isCopy);
+ if (pUser == NULL)
+ return 0; // pending Exception
}
if (domain != 0) {
- pDomain = (CHAR *)(*env)->GetStringUTFChars(env, domain, &isCopy);
+ pDomain = JNU_GetStringPlatformChars(env, domain, &isCopy);
+ if (pDomain == NULL) {
+ if (pUser != NULL)
+ JNU_ReleaseStringPlatformChars(env, user, pUser);
+ return 0; // pending Exception
+ }
}
if (password != 0) {
- pPassword = (CHAR *)(*env)->GetStringUTFChars(env, password, &isCopy);
+ pPassword = JNU_GetStringPlatformChars(env, password, &isCopy);
+ if (pPassword == NULL) {
+ if(pUser != NULL)
+ JNU_ReleaseStringPlatformChars(env, user, pUser);
+ if(pDomain != NULL)
+ JNU_ReleaseStringPlatformChars(env, domain, pDomain);
+ return 0; // pending Exception
+ }
}
pCred = (CredHandle *)malloc(sizeof (CredHandle));
@@ -167,6 +183,14 @@
pCred, <ime
);
+ /* Release resources held by JNU_GetStringPlatformChars */
+ if (pUser != NULL)
+ JNU_ReleaseStringPlatformChars(env, user, pUser);
+ if (pPassword != NULL)
+ JNU_ReleaseStringPlatformChars(env, password, pPassword);
+ if (pDomain != NULL)
+ JNU_ReleaseStringPlatformChars(env, domain, pDomain);
+
if (ss == 0) {
return (jlong) pCred;
} else {
@@ -181,7 +205,6 @@
VOID *pInput = 0;
DWORD inputLen;
CHAR buffOut[512];
- DWORD pcbBuffOut;
jboolean isCopy;
SECURITY_STATUS ss;
SecBufferDesc OutBuffDesc;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/io/FileOutputStream/AtomicAppend.java Mon Mar 17 11:53:36 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");}
+}
--- a/jdk/test/java/lang/ProcessBuilder/Basic.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/test/java/lang/ProcessBuilder/Basic.java Mon Mar 17 11:53:36 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<String> childArgs = new ArrayList<String>(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<String> childArgs = new ArrayList<String>(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<String> 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("<<ALL FILES>>", "execute");
+ final Permission rxPermission
+ = new FilePermission("<<ALL FILES>>", "read,execute");
+ final Permission wxPermission
+ = new FilePermission("<<ALL FILES>>", "write,execute");
+ final Permission rwxPermission
+ = new FilePermission("<<ALL FILES>>", "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;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/InterfaceAddress/Equals.java Mon Mar 17 11:53:36 2008 -0700
@@ -0,0 +1,119 @@
+/*
+ * 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 6628576
+ * @summary InterfaceAddress.equals() NPE when broadcast field == null
+ */
+
+import java.net.InterfaceAddress;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+
+public class Equals
+{
+ public static void main(String[] args) {
+ InterfaceAddress ia1;
+ InterfaceAddress ia2;
+ InetAddress loopbackAddr = InetAddress.getLoopbackAddress();
+ InetAddress broadcast1 = null;
+ InetAddress broadcast2 = null;
+
+ try {
+ broadcast1 = InetAddress.getByName("255.255.255.0");
+ broadcast2 = InetAddress.getByName("255.255.0.0");
+ } catch (UnknownHostException e) {
+ e.printStackTrace();
+ }
+
+ ia1 = createInterfaceAddress(loopbackAddr, (InetAddress) null, (short)45);
+ ia2 = createInterfaceAddress(loopbackAddr, (InetAddress) null, (short)45);
+
+ compare(ia1, ia2, true);
+
+ ia2 = createInterfaceAddress(loopbackAddr, broadcast1, (short)45);
+ compare(ia1, ia2, false);
+
+ ia2 = createInterfaceAddress((InetAddress)null, broadcast1, (short)45);
+ compare(ia1, ia2, false);
+
+ ia1 = createInterfaceAddress(loopbackAddr, broadcast2, (short)45);
+ ia2 = createInterfaceAddress(loopbackAddr, broadcast2, (short)45);
+ compare(ia1, ia2, true);
+
+ ia1.equals(null);
+ }
+
+ static void compare(InterfaceAddress ia1, InterfaceAddress ia2, boolean equal) {
+ if (ia1.equals(ia2) != equal)
+ throw new RuntimeException("Failed: " + ia1 + " not equals to " + ia2);
+
+ if (ia2.equals(ia1) != equal)
+ throw new RuntimeException("Failed: " + ia2 + " not equals to " + ia1);
+ }
+
+ /**
+ * Returns an InterfaceAddress instance with its fields set the the values
+ * specificed.
+ */
+ static InterfaceAddress createInterfaceAddress(
+ InetAddress address, InetAddress broadcast, short prefixlength) {
+ try {
+ Class<InterfaceAddress> IAClass = InterfaceAddress.class;
+ InterfaceAddress ia;
+ Constructor<InterfaceAddress> ctr = IAClass.getDeclaredConstructor();
+ ctr.setAccessible(true);
+
+ Field addressField = IAClass.getDeclaredField("address");
+ addressField.setAccessible(true);
+
+ Field broadcastField = IAClass.getDeclaredField("broadcast");
+ broadcastField.setAccessible(true);
+
+ Field maskLengthField = IAClass.getDeclaredField("maskLength");
+ maskLengthField.setAccessible(true);
+
+ ia = ctr.newInstance();
+ addressField.set(ia, address);
+ broadcastField.set(ia, broadcast);
+ maskLengthField.setShort(ia, prefixlength);
+
+ return ia;
+ } catch (NoSuchFieldException nsfe) {
+ nsfe.printStackTrace();
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ } catch (InstantiationException ie) {
+ ie.printStackTrace();
+ } catch (IllegalAccessException iae) {
+ iae.printStackTrace();
+ } catch (InvocationTargetException ite) {
+ ite.printStackTrace();
+ }
+
+ return null;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/channels/Channels/ShortWrite.java Mon Mar 17 11:53:36 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<buf.length; i++) {
+ int len = buf.length-i;
+ out.write(buf, i, len);
+ expected += len;
+ }
+ System.out.format("Bytes written: %d, expected: %d\n", bytesWritten,
+ expected);
+ if (bytesWritten != expected)
+ throw new RuntimeException("incorrect number of bytes written");
+
+ }
+}
--- a/jdk/test/java/nio/channels/TestUtil.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/test/java/nio/channels/TestUtil.java Mon Mar 17 11:53:36 2008 -0700
@@ -37,7 +37,7 @@
// Test hosts used by the channels tests - change these when
// executing in a different network.
public static final String HOST = "javaweb.sfbay.sun.com";
- public static final String REFUSING_HOST = "jano.sfbay.sun.com";
+ public static final String REFUSING_HOST = "jano1.sfbay.sun.com";
public static final String FAR_HOST = "theclub.ireland.sun.com";
public static final String UNRESOLVABLE_HOST = "blah-blah.blah-blah.blah";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/AccessControlContext/FailureDebugOption.java Mon Mar 17 11:53:36 2008 -0700
@@ -0,0 +1,50 @@
+/*
+ * 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 6648816
+ * @summary REGRESSION: setting -Djava.security.debug=failure result in NPE
+ * in ACC
+ * @run main/othervm -Djava.security.debug=failure FailureDebugOption
+ */
+
+import java.security.ProtectionDomain;
+import java.security.AccessController;
+import java.security.AccessControlException;
+import java.security.BasicPermission;
+
+public class FailureDebugOption {
+
+ public static void main (String argv[]) throws Exception {
+ try {
+ AccessController.checkPermission(
+ new BasicPermission("no such permission"){});
+ } catch (NullPointerException npe) {
+ throw new Exception("Unexpected NullPointerException for security" +
+ " debug option, -Djava.security.debug=failure");
+ } catch (AccessControlException ace) {
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Map/LockStep.java Mon Mar 17 11:53:36 2008 -0700
@@ -0,0 +1,127 @@
+/*
+ * 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 6612102
+ * @summary Test Map implementations for mutual compatibility
+ */
+
+import java.util.*;
+import java.util.concurrent.*;
+
+/**
+ * Based on the strange scenario required to reproduce
+ * (coll) IdentityHashMap.iterator().remove() might decrement size twice
+ *
+ * It would be good to add more "Lockstep-style" tests to this file.
+ */
+public class LockStep {
+ void mapsEqual(Map m1, Map m2) {
+ equal(m1, m2);
+ equal(m2, m1);
+ equal(m1.size(), m2.size());
+ equal(m1.isEmpty(), m2.isEmpty());
+ equal(m1.keySet(), m2.keySet());
+ equal(m2.keySet(), m1.keySet());
+ }
+
+ void mapsEqual(List<Map> maps) {
+ Map first = maps.get(0);
+ for (Map map : maps)
+ mapsEqual(first, map);
+ }
+
+ void put(List<Map> maps, Object key, Object val) {
+ for (Map map : maps)
+ map.put(key, val);
+ mapsEqual(maps);
+ }
+
+ void removeLastTwo(List<Map> 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<Map> 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");}
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/DelayQueue/Stress.java Mon Mar 17 11:53:36 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<Delayed> q = new DelayQueue<Delayed>();
+ 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();
+ }
+}
--- a/jdk/test/java/util/concurrent/LinkedBlockingQueue/OfferRemoveLoops.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/test/java/util/concurrent/LinkedBlockingQueue/OfferRemoveLoops.java Mon Mar 17 11:53:36 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<String> 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();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/BasicCancelTest.java Mon Mar 17 11:53:36 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<? extends Throwable> 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);}}
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/Stress.java Mon Mar 17 11:53:36 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);
+ }
+}
--- a/jdk/test/java/util/concurrent/SynchronousQueue/Fairness.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/test/java/util/concurrent/SynchronousQueue/Fairness.java Mon Mar 17 11:53:36 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<Integer> 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<Integer>());
testFairness(false, new SynchronousQueue<Integer>(false));
testFairness(true, new SynchronousQueue<Integer>(true));
--- a/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/Count.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/Count.java Mon Mar 17 11:53:36 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<? extends Throwable> 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> T serialClone(T obj) {
+ try { return (T) readObject(serializedForm(obj)); }
+ catch (Exception e) { throw new RuntimeException(e); }}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/mxbean/JMXServiceURLTest.java Mon Mar 17 11:53:36 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);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/query/QueryDottedAttrTest.java Mon Mar 17 11:53:36 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 <T> AttrWithDot(Object impl, Class<T> 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<ObjectName> 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);
+ }
+}
--- a/jdk/test/javax/management/query/QueryExpStringTest.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/test/javax/management/query/QueryExpStringTest.java Mon Mar 17 11:53:36 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);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/query/QueryParseTest.java Mon Mar 17 11:53:36 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<ObjectName> 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);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/security/auth/x500/X500Principal/RFC4514.java Mon Mar 17 11:53:36 2008 -0700
@@ -0,0 +1,92 @@
+/*
+ * 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 javax.security.auth.x500.X500Principal;
+
+/**
+ * @test
+ * @bug 6611991
+ * @summary Add support for parsing RFC 4514 DNs to X500Principal
+ *
+ * Ensure RFC 4514 Distinguished Name Strings can be parsed by X500Principal.
+ * RFC 4514 obsoleted RFC 2253 so we should make sure we can parse DNs of
+ * that form that contain subtle differences or clarifications in the grammar.
+ */
+public class RFC4514 {
+
+ private int failed = 0;
+
+ public static void main(String[] args) throws Exception {
+ new RFC4514().test();
+ }
+
+ private void test() throws Exception {
+
+ /**
+ * RFC 4514 allows space to be escaped as '\ '.
+ */
+ parse("CN=\\ Space\\ ,C=US");
+ parse("CN=Sp\\ ace,C=US");
+ /**
+ * RFC 4514 does not require escaping of '=' characters.
+ */
+ parse("CN=Eq=uals,C=US");
+ /**
+ * RFC 4514 requires the null character to be escaped.
+ */
+ parse("CN=\\00,C=US");
+ /**
+ * RFC 4514 does not require escaping of non-leading '#' characters.
+ */
+ parse("CN=Num#ber,C=US");
+ /**
+ * XMLDSig (http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/)
+ * allows implementations to escape trailing whitespace as '\20'.
+ */
+ parse("CN=Trailing \\20,C=US");
+ /**
+ * XMLDSig allows implementations to escape ASCII control characters
+ * (Unicode range \x00 - \x1f) by replacing them with "\" followed by
+ * a two digit hex number showing its Unicode number.
+ */
+ parse("CN=Con\\09trol,C=US");
+
+ if (failed != 0) {
+ throw new Exception("Some RFC4514 tests FAILED");
+ }
+ }
+
+ public void parse(String dnString) throws Exception {
+
+ System.out.println("Parsing " + dnString);
+ X500Principal dn = new X500Principal(dnString);
+ String dnString2 = dn.getName();
+ X500Principal dn2 = new X500Principal(dnString2);
+ if (dn.equals(dn2)) {
+ System.out.println("PASSED");
+ } else {
+ System.out.println("FAILED");
+ failed++;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/management/jmxremote/bootstrap/JvmstatCountersTest.java Mon Mar 17 11:53:36 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<String, String> 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<String, String> 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<String, String> 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!");
+ }
+}
--- a/jdk/test/sun/net/www/http/ChunkedOutputStream/Test.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/test/sun/net/www/http/ChunkedOutputStream/Test.java Mon Mar 17 11:53:36 2008 -0700
@@ -23,7 +23,7 @@
/**
* @test
- * @bug 5026745
+ * @bug 5026745 6631048
* @run main/othervm/timeout=500 Test
* @summary Cannot flush output stream when writing to an HttpUrlConnection
*/
@@ -158,6 +158,50 @@
exchange.sendResponseHeaders(200, 0);
}
break;
+ case 10: /* test11 */
+ printRequestURI(exchange);
+ is = exchange.getRequestBody();
+ s = read (is, str1.length());
+
+ error = false;
+ for (int i=10; i< 30 * 1024; i++) {
+ byte c = (byte)is.read();
+
+ if (c != (byte)i) {
+ error = true;
+ System.out.println ("error at position " + i);
+ }
+ }
+ if (!s.equals(str1) ) {
+ System.out.println ("received string : " + s);
+ exchange.sendResponseHeaders(500, 0);
+ } else if (error) {
+ System.out.println ("error");
+ exchange.sendResponseHeaders(500, 0);
+ } else {
+ exchange.sendResponseHeaders(200, 0);
+ }
+ break;
+ case 11: /* test12 */
+ printRequestURI(exchange);
+ is = exchange.getRequestBody();
+
+ error = false;
+ for (int i=10; i< 30 * 1024; i++) {
+ byte c = (byte)is.read();
+
+ if (c != (byte)i) {
+ error = true;
+ System.out.println ("error at position " + i);
+ }
+ }
+ if (error) {
+ System.out.println ("error");
+ exchange.sendResponseHeaders(500, 0);
+ } else {
+ exchange.sendResponseHeaders(200, 0);
+ }
+ break;
}
exchange.close();
count ++;
@@ -390,6 +434,56 @@
}
}
+ static void test11 (String u) throws Exception {
+ URL url = new URL (u);
+ System.out.println ("client opening connection to: " + u);
+ HttpURLConnection urlc = (HttpURLConnection)url.openConnection ();
+ urlc.setChunkedStreamingMode (36 * 1024);
+ urlc.setDoOutput(true);
+ urlc.setRequestMethod ("POST");
+ OutputStream os = urlc.getOutputStream ();
+ byte[] buf = new byte [30 * 1024];
+ for (int i=0; i< 30 * 1024; i++) {
+ buf[i] = (byte) i;
+ }
+ /* write a small bit first, and then the large buffer */
+ os.write (str1.getBytes());
+ //os.write (buf, 10, buf.length - 10); /* skip 10 bytes to test offset */
+ os.write (buf, 10, (10 * 1024) - 10);
+ os.write (buf, (10 * 1024), (10 * 1024));
+ os.write (buf, (20 * 1024), (10 * 1024));
+ os.close();
+ InputStream is = urlc.getInputStream();
+ is.close();
+ int ret = urlc.getResponseCode();
+ if (ret != 200) {
+ throw new Exception ("Expected 200: got " + ret);
+ }
+ }
+
+ static void test12 (String u) throws Exception {
+ URL url = new URL (u);
+ System.out.println ("client opening connection to: " + u);
+ HttpURLConnection urlc = (HttpURLConnection)url.openConnection ();
+ urlc.setChunkedStreamingMode (36 * 1024);
+ urlc.setDoOutput(true);
+ urlc.setRequestMethod ("POST");
+ OutputStream os = urlc.getOutputStream ();
+ byte[] buf = new byte [30 * 1024];
+ for (int i=0; i< 30 * 1024; i++) {
+ buf[i] = (byte) i;
+ }
+ os.write (buf, 10, buf.length - 10); /* skip 10 bytes to test offset */
+ os.close();
+ InputStream is = urlc.getInputStream();
+ is.close();
+ int ret = urlc.getResponseCode();
+ if (ret != 200) {
+ throw new Exception ("Expected 200: got " + ret);
+ }
+ }
+
+
static com.sun.net.httpserver.HttpServer httpserver;
public static void main (String[] args) throws Exception {
@@ -411,6 +505,8 @@
test8("http://localhost:"+ port + "/test/test8");
test9("http://localhost:"+ port + "/test/test9");
test10("http://localhost:"+ port + "/test/test10");
+ test11("http://localhost:"+ port + "/test/test11");
+ test12("http://localhost:"+ port + "/test/test12");
} finally {
if (httpserver != null)
httpserver.stop(0);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/DnsFallback.java Mon Mar 17 11:53:36 2008 -0700
@@ -0,0 +1,64 @@
+/*
+ * 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 6673164
+ * @summary dns_fallback parse error
+ */
+
+import sun.security.krb5.*;
+import java.io.*;
+
+public class DnsFallback {
+ public static void main(String[] args) throws Exception {
+ check("true", "true", true);
+ check("false", "true", false);
+ check("true", "false", true);
+ check("false", "false", false);
+ check("true", null, true);
+ check("false", null, false);
+ check(null, "true", true);
+ check(null, "false", false);
+ }
+
+ static void check(String realm, String fallback, boolean output) throws Exception {
+ FileOutputStream fo = new FileOutputStream("dnsfallback.conf");
+ StringBuffer sb = new StringBuffer();
+ sb.append("[libdefaults]\n");
+ if (realm != null) {
+ sb.append("dns_lookup_realm=" + realm + "\n");
+ }
+ if (fallback != null) {
+ sb.append("dns_fallback=" + fallback + "\n");
+ }
+ fo.write(sb.toString().getBytes());
+ fo.close();
+ System.setProperty("java.security.krb5.conf", "dnsfallback.conf");
+ Config.refresh();
+ System.out.println("Testing " + realm + ", " + fallback + ", " + output);
+ if (Config.getInstance().useDNS_Realm() != output) {
+ throw new Exception("Fail");
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/AsyncSSLSocketClose.java Mon Mar 17 11:53:36 2008 -0700
@@ -0,0 +1,116 @@
+/*
+ * 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 6447412
+ * @summary Issue with socket.close() for ssl sockets when poweroff on
+ * other system
+ */
+
+import javax.net.ssl.*;
+import java.io.*;
+
+public class AsyncSSLSocketClose implements Runnable
+{
+ SSLSocket socket;
+ SSLServerSocket ss;
+
+ // Where do we find the keystores?
+ static String pathToStores = "../../../../../../../etc";
+ static String keyStoreFile = "keystore";
+ static String trustStoreFile = "truststore";
+ static String passwd = "passphrase";
+
+ public static void main(String[] args) {
+ String keyFilename =
+ System.getProperty("test.src", "./") + "/" + pathToStores +
+ "/" + keyStoreFile;
+ String trustFilename =
+ System.getProperty("test.src", "./") + "/" + pathToStores +
+ "/" + trustStoreFile;
+
+ System.setProperty("javax.net.ssl.keyStore", keyFilename);
+ System.setProperty("javax.net.ssl.keyStorePassword", passwd);
+ System.setProperty("javax.net.ssl.trustStore", trustFilename);
+ System.setProperty("javax.net.ssl.trustStorePassword", passwd);
+
+ new AsyncSSLSocketClose();
+ }
+
+ public AsyncSSLSocketClose() {
+ try {
+ SSLServerSocketFactory sslssf =
+ (SSLServerSocketFactory)SSLServerSocketFactory.getDefault();
+ ss = (SSLServerSocket) sslssf.createServerSocket(0);
+
+ SSLSocketFactory sslsf =
+ (SSLSocketFactory)SSLSocketFactory.getDefault();
+ socket = (SSLSocket)sslsf.createSocket("localhost",
+ ss.getLocalPort());
+ SSLSocket serverSoc = (SSLSocket) ss.accept();
+ ss.close();
+
+ (new Thread(this)).start();
+ serverSoc.startHandshake();
+
+ try {
+ Thread.sleep(5000);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ socket.setSoLinger(true, 10);
+ System.out.println("Calling Socket.close");
+ socket.close();
+ System.out.println("ssl socket get closed");
+ System.out.flush();
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ // block in write
+ public void run() {
+ try {
+ byte[] ba = new byte[1024];
+ for (int i=0; i<ba.length; i++)
+ ba[i] = 0x7A;
+
+ OutputStream os = socket.getOutputStream();
+ int count = 0;
+ while (true) {
+ count += ba.length;
+ System.out.println(count + " bytes to be written");
+ os.write(ba);
+ System.out.println(count + " bytes written");
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/CloseKeepAliveCached.java Mon Mar 17 11:53:36 2008 -0700
@@ -0,0 +1,308 @@
+/*
+ * 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 6618387
+ * @summary SSL client sessions do not close cleanly. A TCP reset occurs
+ * instead of a close_notify alert.
+ * @run main/othervm -Djavax.net.debug=ssl CloseKeepAliveCached
+ *
+ * @ignore
+ * After run the test manually, at the end of the debug output,
+ * if "MainThread, called close()" found, the test passed. Otherwise,
+ * if "Keep-Alive-Timer: called close()", the test failed.
+ */
+
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import javax.net.ssl.*;
+
+public class CloseKeepAliveCached {
+ static Map cookies;
+ ServerSocket ss;
+
+ /*
+ * =============================================================
+ * Set the various variables needed for the tests, then
+ * specify what tests to run on each side.
+ */
+
+ /*
+ * Should we run the client or server in a separate thread?
+ * Both sides can throw exceptions, but do you have a preference
+ * as to which side should be the main thread.
+ */
+ static boolean separateServerThread = true;
+
+ /*
+ * Where do we find the keystores?
+ */
+ static String pathToStores = "../../../../../../etc";
+ static String keyStoreFile = "keystore";
+ static String trustStoreFile = "truststore";
+ static String passwd = "passphrase";
+
+ /*
+ * Is the server ready to serve?
+ */
+ volatile static boolean serverReady = false;
+
+ /*
+ * Turn on SSL debugging?
+ */
+ static boolean debug = false;
+
+ private SSLServerSocket sslServerSocket = null;
+
+ /*
+ * Define the server side of the test.
+ *
+ * If the server prematurely exits, serverReady will be set to true
+ * to avoid infinite hangs.
+ */
+ void doServerSide() throws Exception {
+ SSLServerSocketFactory sslssf =
+ (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
+ sslServerSocket =
+ (SSLServerSocket) sslssf.createServerSocket(serverPort);
+ serverPort = sslServerSocket.getLocalPort();
+
+ /*
+ * Signal Client, we're ready for his connect.
+ */
+ serverReady = true;
+ SSLSocket sslSocket = null;
+ try {
+ sslSocket = (SSLSocket) sslServerSocket.accept();
+ for (int i = 0; i < 3 && !sslSocket.isClosed(); i++) {
+ // read request
+ InputStream is = sslSocket.getInputStream ();
+
+ BufferedReader r = new BufferedReader(
+ new InputStreamReader(is));
+ String x;
+ while ((x=r.readLine()) != null) {
+ if (x.length() ==0) {
+ break;
+ }
+ }
+
+
+ PrintStream out = new PrintStream(
+ new BufferedOutputStream(
+ sslSocket.getOutputStream() ));
+
+ /* send the header */
+ out.print("HTTP/1.1 200 OK\r\n");
+ out.print("Keep-Alive: timeout=15, max=100\r\n");
+ out.print("Connection: Keep-Alive\r\n");
+ out.print("Content-Type: text/html; charset=iso-8859-1\r\n");
+ out.print("Content-Length: 9\r\n");
+ out.print("\r\n");
+ out.print("Testing\r\n");
+ out.flush();
+
+ Thread.sleep(50);
+ }
+ sslSocket.close();
+ sslServerSocket.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /*
+ * Define the client side of the test.
+ *
+ * If the server prematurely exits, serverReady will be set to true
+ * to avoid infinite hangs.
+ */
+ void doClientSide() throws Exception {
+
+ /*
+ * Wait for server to get started.
+ */
+ while (!serverReady) {
+ Thread.sleep(50);
+ }
+ try {
+ HttpsURLConnection http = null;
+
+ /* establish http connection to server */
+ URL url = new URL("https://localhost:" + serverPort+"/");
+ HttpsURLConnection.setDefaultHostnameVerifier(new NameVerifier());
+ http = (HttpsURLConnection)url.openConnection();
+ InputStream is = http.getInputStream ();
+ while (is.read() != -1);
+ is.close();
+
+ url = new URL("https://localhost:" + serverPort+"/");
+ http = (HttpsURLConnection)url.openConnection();
+ is = http.getInputStream ();
+ while (is.read() != -1);
+
+ // if inputstream.close() called, the http.disconnect() will
+ // not able to close the cached connection. If application
+ // wanna close the keep-alive cached connection immediately
+ // with httpURLConnection.disconnect(), they should not call
+ // inputstream.close() explicitly, the
+ // httpURLConnection.disconnect() will do it internally.
+ // is.close();
+
+ // close the connection, sending close_notify to peer.
+ // otherwise, the connection will be closed by Finalizer or
+ // Keep-Alive-Timer if timeout.
+ http.disconnect();
+ // Thread.sleep(5000);
+ } catch (IOException ioex) {
+ if (sslServerSocket != null)
+ sslServerSocket.close();
+ throw ioex;
+ }
+ }
+
+ static class NameVerifier implements HostnameVerifier {
+ public boolean verify(String hostname, SSLSession session) {
+ return true;
+ }
+ }
+
+ /*
+ * =============================================================
+ * The remainder is just support stuff
+ */
+
+ // use any free port by default
+ volatile int serverPort = 0;
+
+ volatile Exception serverException = null;
+ volatile Exception clientException = null;
+
+ public static void main(String args[]) throws Exception {
+ String keyFilename =
+ System.getProperty("test.src", "./") + "/" + pathToStores +
+ "/" + keyStoreFile;
+ String trustFilename =
+ System.getProperty("test.src", "./") + "/" + pathToStores +
+ "/" + trustStoreFile;
+
+ System.setProperty("javax.net.ssl.keyStore", keyFilename);
+ System.setProperty("javax.net.ssl.keyStorePassword", passwd);
+ System.setProperty("javax.net.ssl.trustStore", trustFilename);
+ System.setProperty("javax.net.ssl.trustStorePassword", passwd);
+
+ if (debug)
+ System.setProperty("javax.net.debug", "all");
+
+ /*
+ * Start the tests.
+ */
+ new CloseKeepAliveCached();
+ }
+
+ Thread clientThread = null;
+ Thread serverThread = null;
+ /*
+ * Primary constructor, used to drive remainder of the test.
+ *
+ * Fork off the other side, then do your work.
+ */
+ CloseKeepAliveCached() throws Exception {
+ if (separateServerThread) {
+ startServer(true);
+ startClient(false);
+ } else {
+ startClient(true);
+ startServer(false);
+ }
+
+ /*
+ * Wait for other side to close down.
+ */
+ if (separateServerThread) {
+ serverThread.join();
+ } else {
+ clientThread.join();
+ }
+
+ /*
+ * When we get here, the test is pretty much over.
+ *
+ * If the main thread excepted, that propagates back
+ * immediately. If the other thread threw an exception, we
+ * should report back.
+ */
+ if (serverException != null)
+ throw serverException;
+ if (clientException != null)
+ throw clientException;
+ }
+
+ void startServer(boolean newThread) throws Exception {
+ if (newThread) {
+ serverThread = new Thread() {
+ public void run() {
+ try {
+ doServerSide();
+ } catch (Exception e) {
+ /*
+ * Our server thread just died.
+ *
+ * Release the client, if not active already...
+ */
+ System.err.println("Server died...");
+ serverReady = true;
+ serverException = e;
+ }
+ }
+ };
+ serverThread.start();
+ } else {
+ doServerSide();
+ }
+ }
+
+ void startClient(boolean newThread) throws Exception {
+ if (newThread) {
+ clientThread = new Thread() {
+ public void run() {
+ try {
+ doClientSide();
+ } catch (Exception e) {
+ /*
+ * Our client thread just died.
+ */
+ System.err.println("Client died...");
+ clientException = e;
+ }
+ }
+ };
+ clientThread.start();
+ } else {
+ doClientSide();
+ }
+ }
+}
+
--- a/jdk/test/sun/security/tools/keytool/StartDateTest.java Thu Mar 06 16:06:45 2008 -0800
+++ b/jdk/test/sun/security/tools/keytool/StartDateTest.java Mon Mar 17 11:53:36 2008 -0700
@@ -52,15 +52,15 @@
cal.setTime(getIssueDate());
System.out.println(cal);
if (cal.get(Calendar.YEAR) != year + 1) {
- throw new Exception("Function #1 check fails");
+ throw new Exception("Function check #1 fails");
}
run("-keystore jks -storetype jks -storepass changeit -keypass changeit -alias me " +
"-selfcert -startdate +1m");
cal.setTime(getIssueDate());
System.out.println(cal);
- if (cal.get(Calendar.MONTH) != month + 1) {
- throw new Exception("Function #1 check fails");
+ if (cal.get(Calendar.MONTH) != (month + 1) % 12) {
+ throw new Exception("Function check #2 fails");
}
new File("jks").delete();