--- a/jdk/make/sun/awt/FILES_c_unix.gmk Thu May 30 10:58:21 2013 -0700
+++ b/jdk/make/sun/awt/FILES_c_unix.gmk Mon Jun 03 23:23:20 2013 -0700
@@ -171,3 +171,13 @@
GLXSurfaceData.c \
AccelGlyphCache.c \
CUPSfuncs.c
+
+ifeq ($(PLATFORM), macosx)
+FILES_NO_MOTIF_objc = \
+ AWTFont.m \
+ AWTStrike.m \
+ CCharToGlyphMapper.m \
+ CGGlyphImages.m \
+ CGGlyphOutlines.m \
+ CoreTextSupport.m
+endif # PLATFORM
--- a/jdk/make/sun/awt/FILES_export_unix.gmk Thu May 30 10:58:21 2013 -0700
+++ b/jdk/make/sun/awt/FILES_export_unix.gmk Mon Jun 03 23:23:20 2013 -0700
@@ -187,3 +187,14 @@
java/awt/dnd/DnDConstants.java \
sun/awt/CausedFocusEvent.java
+ifeq ($(PLATFORM), macosx)
+ifeq ($(HEADLESS), true)
+FILES_export += \
+ sun/awt/SunHints.java \
+ sun/font/CCharToGlyphMapper.java \
+ sun/font/CFont.java \
+ sun/font/CFontManager.java \
+ sun/font/CStrike.java \
+ sun/font/CStrikeDisposer.java
+endif # HEADLESS
+endif # PLATFORM
--- a/jdk/make/sun/awt/mawt.gmk Thu May 30 10:58:21 2013 -0700
+++ b/jdk/make/sun/awt/mawt.gmk Mon Jun 03 23:23:20 2013 -0700
@@ -43,6 +43,10 @@
# compiled based on the motif version.
FILES_c = $(FILES_NO_MOTIF_c)
+ifeq ($(PLATFORM), macosx)
+FILES_objc = $(FILES_NO_MOTIF_objc)
+endif # PLATFORM
+
ifeq ($(PLATFORM), solaris)
ifneq ($(ARCH), amd64)
FILES_reorder += reorder-$(ARCH)
@@ -97,6 +101,10 @@
vpath %.cpp $(SHARE_SRC)/native/$(PKGDIR)/image
vpath %.c $(PLATFORM_SRC)/native/$(PKGDIR)/robot_child
+ifeq ($(PLATFORM), macosx)
+vpath %.m $(call NativeSrcDirList,,native/sun/font)
+endif # PLATFORM
+
#
# Libraries to link in.
#
@@ -192,13 +200,21 @@
$(EVENT_MODEL)
ifeq ($(PLATFORM), macosx)
-CPPFLAGS += -I$(CUPS_HEADERS_PATH)
+CPPFLAGS += -I$(CUPS_HEADERS_PATH) \
+ $(call NativeSrcDirList,-I,native/sun/awt) \
+ $(call NativeSrcDirList,-I,native/sun/font)
ifndef HEADLESS
CPPFLAGS += -I$(MOTIF_DIR)/include \
-I$(OPENWIN_HOME)/include
LDFLAGS += -L$(MOTIF_LIB) -L$(OPENWIN_LIB)
-
+else
+LDFLAGS += -framework Accelerate \
+ -framework ApplicationServices \
+ -framework Cocoa \
+ -F/System/Library/Frameworks/JavaVM.framework/Frameworks \
+ -framework JavaNativeFoundation \
+ -framework JavaRuntimeSupport
endif # !HEADLESS
endif # PLATFORM
--- a/jdk/makefiles/CompileNativeLibraries.gmk Thu May 30 10:58:21 2013 -0700
+++ b/jdk/makefiles/CompileNativeLibraries.gmk Mon Jun 03 23:23:20 2013 -0700
@@ -2314,6 +2314,10 @@
$(JDK_TOPDIR)/src/solaris/native/sun/java2d/opengl \
$(JDK_TOPDIR)/src/solaris/native/sun/java2d/x11
+ifeq ($(OPENJDK_TARGET_OS),macosx)
+ LIBAWT_HEADLESS_DIRS+=$(JDK_TOPDIR)/src/macosx/native/sun/font
+endif
+
LIBAWT_HEADLESS_CFLAGS:=-DHEADLESS=true \
-DX11_PATH=\"$(X11_PATH)\" -DPACKAGE_PATH=\"$(PACKAGE_PATH)\" \
$(CUPS_CFLAGS) \
@@ -2328,6 +2332,12 @@
-I$(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/jdga \
$(foreach dir,$(LIBAWT_HEADLESS_DIRS),-I$(dir))
+ifeq ($(OPENJDK_TARGET_OS),macosx)
+ LIBAWT_HEADLESS_CFLAGS+=\
+ -F/System/Library/Frameworks/JavaVM.framework/Frameworks \
+ -F/System/Library/Frameworks/ApplicationServices.framework/Frameworks
+endif
+
LIBAWT_HEADLESS_FILES:=\
awt_Font.c \
HeadlessToolkit.c \
@@ -2356,6 +2366,16 @@
AccelGlyphCache.c \
CUPSfuncs.c
+ifeq ($(OPENJDK_TARGET_OS),macosx)
+ LIBAWT_HEADLESS_FILES+=\
+ AWTFont.m \
+ AWTStrike.m \
+ CCharToGlyphMapper.m \
+ CGGlyphImages.m \
+ CGGlyphOutlines.m \
+ CoreTextSupport.m
+endif
+
LIBAWT_HEADLESS_REORDER:=
ifeq ($(OPENJDK_TARGET_OS), solaris)
ifneq ($(OPENJDK_TARGET_CPU), x86_64)
@@ -2382,7 +2402,13 @@
REORDER:=$(LIBAWT_HEADLESS_REORDER), \
LDFLAGS_SUFFIX_linux:=-ljvm -lawt -lm $(LIBDL) -ljava,\
LDFLAGS_SUFFIX_solaris:=$(LIBDL) -ljvm -lawt -lm -ljava $(LIBCXX) -lc,\
- LDFLAGS_SUFFIX_macosx:=-ljvm $(LIBCXX) -lawt $(LIBDL) -ljava,\
+ LDFLAGS_SUFFIX_macosx:=-ljvm $(LIBCXX) -lawt $(LIBDL) -ljava \
+ -framework Accelerate \
+ -framework ApplicationServices \
+ -framework Cocoa \
+ -F/System/Library/Frameworks/JavaVM.framework/Frameworks \
+ -framework JavaNativeFoundation \
+ -framework JavaRuntimeSupport,\
OBJECT_DIR:=$(JDK_OUTPUTDIR)/objs/libawt_headless,\
DEBUG_SYMBOLS:=$(DEBUG_ALL_BINARIES)))
--- a/jdk/src/macosx/bin/java_md_macosx.c Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/macosx/bin/java_md_macosx.c Mon Jun 03 23:23:20 2013 -0700
@@ -44,7 +44,6 @@
#include <Cocoa/Cocoa.h>
#include <objc/objc-runtime.h>
#include <objc/objc-auto.h>
-#include <dispatch/dispatch.h>
#include <errno.h>
#include <spawn.h>
@@ -1001,6 +1000,32 @@
setenv(envVar, "1", 1);
}
+/* This class is made for performSelectorOnMainThread when java main
+ * should be launched on main thread.
+ * We cannot use dispatch_sync here, because it blocks the main dispatch queue
+ * which is used inside Cocoa
+ */
+@interface JavaLaunchHelper : NSObject {
+ int _returnValue;
+}
+- (void) launchJava:(NSValue*)argsValue;
+- (int) getReturnValue;
+@end
+
+@implementation JavaLaunchHelper
+
+- (void) launchJava:(NSValue*)argsValue
+{
+ _returnValue = JavaMain([argsValue pointerValue]);
+}
+
+- (int) getReturnValue
+{
+ return _returnValue;
+}
+
+@end
+
// MacOSX we may continue in the same thread
int
JVMInit(InvocationFunctions* ifn, jlong threadStackSize,
@@ -1010,16 +1035,22 @@
JLI_TraceLauncher("In same thread\n");
// need to block this thread against the main thread
// so signals get caught correctly
- __block int rslt;
- dispatch_sync(dispatch_get_main_queue(), ^(void) {
- JavaMainArgs args;
- args.argc = argc;
- args.argv = argv;
- args.mode = mode;
- args.what = what;
- args.ifn = *ifn;
- rslt = JavaMain((void*)&args);
- });
+ JavaMainArgs args;
+ args.argc = argc;
+ args.argv = argv;
+ args.mode = mode;
+ args.what = what;
+ args.ifn = *ifn;
+ int rslt;
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ {
+ JavaLaunchHelper* launcher = [[[JavaLaunchHelper alloc] init] autorelease];
+ [launcher performSelectorOnMainThread:@selector(launchJava:)
+ withObject:[NSValue valueWithPointer:(void*)&args]
+ waitUntilDone:YES];
+ rslt = [launcher getReturnValue];
+ }
+ [pool drain];
return rslt;
} else {
return ContinueInNewThread(ifn, threadStackSize, argc, argv, mode, what, ret);
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java Mon Jun 03 23:23:20 2013 -0700
@@ -38,7 +38,7 @@
private long fNativeDropTransfer = 0;
private long fNativeDataAvailable = 0;
private Object fNativeData = null;
- private boolean insideTarget = false;
+ private boolean insideTarget = true;
Object awtLockAccess = new Object();
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. 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
@@ -115,6 +115,8 @@
static final int RESIZABLE = 1 << 9; // both a style bit and prop bit
static final int NONACTIVATING = 1 << 24;
+ static final int IS_DIALOG = 1 << 25;
+ static final int IS_MODAL = 1 << 26;
static final int _STYLE_PROP_BITMASK = DECORATED | TEXTURED | UNIFIED | UTILITY | HUD | SHEET | CLOSEABLE | MINIMIZABLE | RESIZABLE;
@@ -374,6 +376,13 @@
}
}
+ if (isDialog) {
+ styleBits = SET(styleBits, IS_DIALOG, true);
+ if (((Dialog) target).isModal()) {
+ styleBits = SET(styleBits, IS_MODAL, true);
+ }
+ }
+
peer.setTextured(IS(TEXTURED, styleBits));
return styleBits;
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPrinterJob.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPrinterJob.java Mon Jun 03 23:23:20 2013 -0700
@@ -36,6 +36,7 @@
import javax.print.*;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.HashPrintRequestAttributeSet;
+import javax.print.attribute.standard.PageRanges;
import sun.java2d.*;
import sun.print.*;
@@ -173,6 +174,19 @@
if (nsPrintInfo != null) {
fNSPrintInfo = nsPrintInfo.getValue();
}
+
+ PageRanges pageRangesAttr = (PageRanges)attributes.get(PageRanges.class);
+ if (isSupportedValue(pageRangesAttr, attributes)) {
+ SunPageSelection rangeSelect = (SunPageSelection)attributes.get(SunPageSelection.class);
+ // If rangeSelect is not null, we are using AWT's print dialog that has
+ // All, Selection, and Range radio buttons
+ if (rangeSelect == null || rangeSelect == SunPageSelection.RANGE) {
+ int[][] range = pageRangesAttr.getMembers();
+ // setPageRange will set firstPage and lastPage as called in getFirstPage
+ // and getLastPage
+ setPageRange(range[0][0] - 1, range[0][1] - 1);
+ }
+ }
}
volatile boolean onEventThread;
@@ -225,7 +239,6 @@
* the end of the document. Note that firstPage
* and lastPage are 0 based page indices.
*/
- int numPages = mDocument.getNumberOfPages();
int firstPage = getFirstPage();
int lastPage = getLastPage();
@@ -242,42 +255,53 @@
userCancelled = false;
}
- if (EventQueue.isDispatchThread()) {
- // This is an AWT EventQueue, and this print rendering loop needs to block it.
-
- onEventThread = true;
+ //Add support for PageRange
+ PageRanges pr = (attributes == null) ? null
+ : (PageRanges)attributes.get(PageRanges.class);
+ int[][] prMembers = (pr == null) ? new int[0][0] : pr.getMembers();
+ int loopi = 0;
+ do {
+ if (EventQueue.isDispatchThread()) {
+ // This is an AWT EventQueue, and this print rendering loop needs to block it.
- printingLoop = AccessController.doPrivileged(new PrivilegedAction<SecondaryLoop>() {
- @Override
- public SecondaryLoop run() {
- return Toolkit.getDefaultToolkit()
- .getSystemEventQueue()
- .createSecondaryLoop();
- }
- });
+ onEventThread = true;
+
+ printingLoop = AccessController.doPrivileged(new PrivilegedAction<SecondaryLoop>() {
+ @Override
+ public SecondaryLoop run() {
+ return Toolkit.getDefaultToolkit()
+ .getSystemEventQueue()
+ .createSecondaryLoop();
+ }
+ });
- try {
- // Fire off the print rendering loop on the AppKit thread, and don't have
- // it wait and block this thread.
- if (printLoop(false, firstPage, lastPage)) {
- // Start a secondary loop on EDT until printing operation is finished or cancelled
- printingLoop.enter();
+ try {
+ // Fire off the print rendering loop on the AppKit thread, and don't have
+ // it wait and block this thread.
+ if (printLoop(false, firstPage, lastPage)) {
+ // Start a secondary loop on EDT until printing operation is finished or cancelled
+ printingLoop.enter();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
}
- } catch (Exception e) {
- e.printStackTrace();
+ } else {
+ // Fire off the print rendering loop on the AppKit, and block this thread
+ // until it is done.
+ // But don't actually block... we need to come back here!
+ onEventThread = false;
+
+ try {
+ printLoop(true, firstPage, lastPage);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
}
- } else {
- // Fire off the print rendering loop on the AppKit, and block this thread
- // until it is done.
- // But don't actually block... we need to come back here!
- onEventThread = false;
-
- try {
- printLoop(true, firstPage, lastPage);
- } catch (Exception e) {
- e.printStackTrace();
+ if (++loopi < prMembers.length) {
+ firstPage = prMembers[loopi][0]-1;
+ lastPage = prMembers[loopi][1] -1;
}
- }
+ } while (loopi < prMembers.length);
} finally {
synchronized (this) {
// NOTE: Native code shouldn't allow exceptions out while
--- a/jdk/src/macosx/native/sun/awt/AWTWindow.m Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/macosx/native/sun/awt/AWTWindow.m Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. 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
@@ -536,8 +536,12 @@
- (void) windowDidBecomeKey: (NSNotification *) notification {
AWT_ASSERT_APPKIT_THREAD;
[AWTToolkit eventCountPlusPlus];
- [CMenuBar activate:self.javaMenuBar modallyDisabled:NO];
AWTWindow *opposite = [AWTWindow lastKeyWindow];
+ if (!IS(self.styleBits, IS_DIALOG)) {
+ [CMenuBar activate:self.javaMenuBar modallyDisabled:NO];
+ } else if (IS(self.styleBits, IS_MODAL)) {
+ [CMenuBar activate:opposite->javaMenuBar modallyDisabled:YES];
+ }
[AWTWindow setLastKeyWindow:nil];
[self _deliverWindowFocusEvent:YES oppositeWindow: opposite];
--- a/jdk/src/macosx/native/sun/font/AWTFont.m Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/macosx/native/sun/font/AWTFont.m Mon Jun 03 23:23:20 2013 -0700
@@ -395,6 +395,7 @@
#pragma mark --- Miscellaneous JNI ---
+#ifndef HEADLESS
/*
* Class: sun_awt_PlatformFont
* Method: initIDs
@@ -416,3 +417,4 @@
(JNIEnv *env, jclass cls)
{
}
+#endif
--- a/jdk/src/share/classes/com/sun/beans/finder/AbstractFinder.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/com/sun/beans/finder/AbstractFinder.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2013, Oracle and/or its affiliates. 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
@@ -24,6 +24,9 @@
*/
package com.sun.beans.finder;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Modifier;
+
import java.util.HashMap;
import java.util.Map;
@@ -37,7 +40,7 @@
*
* @author Sergey A. Malenkov
*/
-abstract class AbstractFinder<T> {
+abstract class AbstractFinder<T extends Executable> {
private final Class<?>[] args;
/**
@@ -53,27 +56,6 @@
}
/**
- * Returns an array of {@code Class} objects
- * that represent the formal parameter types of the method.
- * Returns an empty array if the method takes no parameters.
- *
- * @param method the object that represents method
- * @return the parameter types of the method
- */
- protected abstract Class<?>[] getParameters(T method);
-
- /**
- * Returns {@code true} if and only if the method
- * was declared to take a variable number of arguments.
- *
- * @param method the object that represents method
- * @return {@code true} if the method was declared
- * to take a variable number of arguments;
- * {@code false} otherwise
- */
- protected abstract boolean isVarArgs(T method);
-
- /**
* Checks validness of the method.
* At least the valid method should be public.
*
@@ -81,7 +63,9 @@
* @return {@code true} if the method is valid,
* {@code false} otherwise
*/
- protected abstract boolean isValid(T method);
+ protected boolean isValid(T method) {
+ return Modifier.isPublic(method.getModifiers());
+ }
/**
* Performs a search in the {@code methods} array.
@@ -109,7 +93,7 @@
for (T newMethod : methods) {
if (isValid(newMethod)) {
- Class<?>[] newParams = getParameters(newMethod);
+ Class<?>[] newParams = newMethod.getParameterTypes();
if (newParams.length == this.args.length) {
PrimitiveWrapperMap.replacePrimitivesWithWrappers(newParams);
if (isAssignable(newParams, this.args)) {
@@ -120,6 +104,11 @@
boolean useNew = isAssignable(oldParams, newParams);
boolean useOld = isAssignable(newParams, oldParams);
+ if (useOld && useNew) {
+ // only if parameters are equal
+ useNew = !newMethod.isSynthetic();
+ useOld = !oldMethod.isSynthetic();
+ }
if (useOld == useNew) {
ambiguous = true;
} else if (useNew) {
@@ -130,7 +119,7 @@
}
}
}
- if (isVarArgs(newMethod)) {
+ if (newMethod.isVarArgs()) {
int length = newParams.length - 1;
if (length <= this.args.length) {
Class<?>[] array = new Class<?>[this.args.length];
@@ -160,6 +149,11 @@
boolean useNew = isAssignable(oldParams, newParams);
boolean useOld = isAssignable(newParams, oldParams);
+ if (useOld && useNew) {
+ // only if parameters are equal
+ useNew = !newMethod.isSynthetic();
+ useOld = !oldMethod.isSynthetic();
+ }
if (useOld == useNew) {
if (oldParams == map.get(oldMethod)) {
ambiguous = true;
--- a/jdk/src/share/classes/com/sun/beans/finder/ConstructorFinder.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/com/sun/beans/finder/ConstructorFinder.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2013, Oracle and/or its affiliates. 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
@@ -86,44 +86,4 @@
private ConstructorFinder(Class<?>[] args) {
super(args);
}
-
- /**
- * Returns an array of {@code Class} objects
- * that represent the formal parameter types of the constructor.
- * Returns an empty array if the constructor takes no parameters.
- *
- * @param constructor the object that represents constructor
- * @return the parameter types of the constructor
- */
- @Override
- protected Class<?>[] getParameters(Constructor<?> constructor) {
- return constructor.getParameterTypes();
- }
-
- /**
- * Returns {@code true} if and only if the constructor
- * was declared to take a variable number of arguments.
- *
- * @param constructor the object that represents constructor
- * @return {@code true} if the constructor was declared
- * to take a variable number of arguments;
- * {@code false} otherwise
- */
- @Override
- protected boolean isVarArgs(Constructor<?> constructor) {
- return constructor.isVarArgs();
- }
-
- /**
- * Checks validness of the constructor.
- * The valid constructor should be public.
- *
- * @param constructor the object that represents constructor
- * @return {@code true} if the constructor is valid,
- * {@code false} otherwise
- */
- @Override
- protected boolean isValid(Constructor<?> constructor) {
- return Modifier.isPublic(constructor.getModifiers());
- }
}
--- a/jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2013, Oracle and/or its affiliates. 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
@@ -196,33 +196,6 @@
}
/**
- * Returns an array of {@code Class} objects
- * that represent the formal parameter types of the method.
- * Returns an empty array if the method takes no parameters.
- *
- * @param method the object that represents method
- * @return the parameter types of the method
- */
- @Override
- protected Class<?>[] getParameters(Method method) {
- return method.getParameterTypes();
- }
-
- /**
- * Returns {@code true} if and only if the method
- * was declared to take a variable number of arguments.
- *
- * @param method the object that represents method
- * @return {@code true} if the method was declared
- * to take a variable number of arguments;
- * {@code false} otherwise
- */
- @Override
- protected boolean isVarArgs(Method method) {
- return method.isVarArgs();
- }
-
- /**
* Checks validness of the method.
* The valid method should be public and
* should have the specified name.
@@ -233,6 +206,6 @@
*/
@Override
protected boolean isValid(Method method) {
- return !method.isBridge() && Modifier.isPublic(method.getModifiers()) && method.getName().equals(this.name);
+ return super.isValid(method) && method.getName().equals(this.name);
}
}
--- a/jdk/src/share/classes/com/sun/jndi/toolkit/ctx/Continuation.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/com/sun/jndi/toolkit/ctx/Continuation.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2013, Oracle and/or its affiliates. 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
@@ -90,14 +90,16 @@
* Constructs a new instance of Continuation.
* @param top The name of the object that is to be resolved/operated upon.
* This becomes the Continuation's 'starter' and is used to
- * calculate the "resolved name" when filling in a NamingException.
+ * calculate the "resolved name" when filling in a NamingException.
* @param environment The environment used by the caller. It is used
- * when setting the "environment" of a CannotProceedException.
+ * when setting the "environment" of a CannotProceedException.
*/
+ @SuppressWarnings("unchecked") // For Hashtable clone: environment.clone()
public Continuation(Name top, Hashtable<?,?> environment) {
super();
starter = top;
- this.environment = environment;
+ this.environment = (Hashtable<?,?>)
+ ((environment == null) ? null : environment.clone());
}
/**
--- a/jdk/src/share/classes/com/sun/jndi/toolkit/dir/LazySearchEnumerationImpl.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/com/sun/jndi/toolkit/dir/LazySearchEnumerationImpl.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2013, Oracle and/or its affiliates. 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
@@ -69,6 +69,7 @@
}
}
+ @SuppressWarnings("unchecked") // For Hashtable clone: env.clone()
public LazySearchEnumerationImpl(NamingEnumeration<Binding> candidates,
AttrFilter filter, SearchControls cons,
Context ctx, Hashtable<String, Object> env, boolean useFactory)
@@ -76,7 +77,8 @@
this.candidates = candidates;
this.filter = filter;
- this.env = env;
+ this.env = (Hashtable<String, Object>)
+ ((env == null) ? null : env.clone());
this.context = ctx;
this.useFactory = useFactory;
--- a/jdk/src/share/classes/com/sun/jndi/toolkit/url/GenericURLContext.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/com/sun/jndi/toolkit/url/GenericURLContext.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2013, Oracle and/or its affiliates. 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
@@ -53,7 +53,8 @@
@SuppressWarnings("unchecked") // Expect Hashtable<String, Object>
public GenericURLContext(Hashtable<?,?> env) {
// context that is not tied to any specific URL
- myEnv = (Hashtable<String, Object>)env; // copied on write
+ myEnv =
+ (Hashtable<String, Object>)(env == null ? null : env.clone());
}
public void close() throws NamingException {
@@ -488,22 +489,19 @@
return result;
}
- @SuppressWarnings("unchecked") // clone()
public Object removeFromEnvironment(String propName)
throws NamingException {
if (myEnv == null) {
return null;
}
- myEnv = (Hashtable<String, Object>)myEnv.clone();
return myEnv.remove(propName);
}
- @SuppressWarnings("unchecked") // clone()
public Object addToEnvironment(String propName, Object propVal)
throws NamingException {
- myEnv = (myEnv == null)
- ? new Hashtable<String, Object>(11, 0.75f)
- : (Hashtable<String, Object>)myEnv.clone();
+ if (myEnv == null) {
+ myEnv = new Hashtable<String, Object>(11, 0.75f);
+ }
return myEnv.put(propName, propVal);
}
--- a/jdk/src/share/classes/java/io/FileInputStream.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/io/FileInputStream.java Mon Jun 03 23:23:20 2013 -0700
@@ -240,13 +240,15 @@
*
* <p>The <code>skip</code> method may, for a variety of
* reasons, end up skipping over some smaller number of bytes,
- * possibly <code>0</code>. If <code>n</code> is negative, an
- * <code>IOException</code> is thrown, even though the <code>skip</code>
- * method of the {@link InputStream} superclass does nothing in this case.
- * The actual number of bytes skipped is returned.
+ * possibly <code>0</code>. If <code>n</code> is negative, the method
+ * will try to skip backwards. In case the backing file does not support
+ * backward skip at its current position, an <code>IOException</code> is
+ * thrown. The actual number of bytes skipped is returned. If it skips
+ * forwards, it returns a positive value. If it skips backwards, it
+ * returns a negative value.
*
- * <p>This method may skip more bytes than are remaining in the backing
- * file. This produces no exception and the number of bytes skipped
+ * <p>This method may skip more bytes than what are remaining in the
+ * backing file. This produces no exception and the number of bytes skipped
* may include some number of bytes that were beyond the EOF of the
* backing file. Attempting to read from the stream after skipping past
* the end will result in -1 indicating the end of the file.
@@ -261,9 +263,10 @@
/**
* Returns an estimate of the number of remaining bytes that can be read (or
* skipped over) from this input stream without blocking by the next
- * invocation of a method for this input stream. The next invocation might be
- * the same thread or another thread. A single read or skip of this
- * many bytes will not block, but may read or skip fewer bytes.
+ * invocation of a method for this input stream. Returns 0 when the file
+ * position is beyond EOF. The next invocation might be the same thread
+ * or another thread. A single read or skip of this many bytes will not
+ * block, but may read or skip fewer bytes.
*
* <p> In some cases, a non-blocking read (or skip) may appear to be
* blocked when it is merely slow, for example when reading large
--- a/jdk/src/share/classes/java/io/InputStream.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/io/InputStream.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2013, Oracle and/or its affiliates. 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
@@ -193,8 +193,10 @@
* up skipping over some smaller number of bytes, possibly <code>0</code>.
* This may result from any of a number of conditions; reaching end of file
* before <code>n</code> bytes have been skipped is only one possibility.
- * The actual number of bytes skipped is returned. If <code>n</code> is
- * negative, no bytes are skipped.
+ * The actual number of bytes skipped is returned. If {@code n} is
+ * negative, the {@code skip} method for class {@code InputStream} always
+ * returns 0, and no bytes are skipped. Subclasses may handle the negative
+ * value differently.
*
* <p> The <code>skip</code> method of this class creates a
* byte array and then repeatedly reads into it until <code>n</code> bytes
--- a/jdk/src/share/classes/java/lang/Class.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/lang/Class.java Mon Jun 03 23:23:20 2013 -0700
@@ -28,6 +28,7 @@
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.Member;
import java.lang.reflect.Field;
import java.lang.reflect.Executable;
@@ -115,9 +116,9 @@
* @since JDK1.0
*/
public final class Class<T> implements java.io.Serializable,
- java.lang.reflect.GenericDeclaration,
- java.lang.reflect.Type,
- java.lang.reflect.AnnotatedElement {
+ GenericDeclaration,
+ Type,
+ AnnotatedElement {
private static final int ANNOTATION= 0x00002000;
private static final int ENUM = 0x00004000;
private static final int SYNTHETIC = 0x00001000;
@@ -3182,7 +3183,7 @@
*/
@Override
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
- return AnnotatedElement.super.isAnnotationPresent(annotationClass);
+ return GenericDeclaration.super.isAnnotationPresent(annotationClass);
}
/**
--- a/jdk/src/share/classes/java/lang/String.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/lang/String.java Mon Jun 03 23:23:20 2013 -0700
@@ -1010,13 +1010,14 @@
private boolean nonSyncContentEquals(AbstractStringBuilder sb) {
char v1[] = value;
char v2[] = sb.getValue();
- int i = 0;
- int n = value.length;
- while (n-- != 0) {
+ int n = v1.length;
+ if (n != sb.length()) {
+ return false;
+ }
+ for (int i = 0; i < n; i++) {
if (v1[i] != v2[i]) {
return false;
}
- i++;
}
return true;
}
@@ -1038,8 +1039,6 @@
* @since 1.5
*/
public boolean contentEquals(CharSequence cs) {
- if (value.length != cs.length())
- return false;
// Argument is a StringBuffer, StringBuilder
if (cs instanceof AbstractStringBuilder) {
if (cs instanceof StringBuffer) {
@@ -1055,12 +1054,14 @@
return true;
// Argument is a generic CharSequence
char v1[] = value;
- int i = 0;
- int n = value.length;
- while (n-- != 0) {
- if (v1[i] != cs.charAt(i))
+ int n = v1.length;
+ if (n != cs.length()) {
+ return false;
+ }
+ for (int i = 0; i < n; i++) {
+ if (v1[i] != cs.charAt(i)) {
return false;
- i++;
+ }
}
return true;
}
--- a/jdk/src/share/classes/java/lang/StringBuffer.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/lang/StringBuffer.java Mon Jun 03 23:23:20 2013 -0700
@@ -335,10 +335,8 @@
* @since 1.5
*/
@Override
- public StringBuffer append(CharSequence s) {
- // Note, synchronization achieved via invocations of other StringBuffer methods after
- // narrowing of s to specific type
- // Ditto for toStringCache clearing
+ public synchronized StringBuffer append(CharSequence s) {
+ toStringCache = null;
super.append(s);
return this;
}
--- a/jdk/src/share/classes/java/lang/Thread.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/lang/Thread.java Mon Jun 03 23:23:20 2013 -0700
@@ -145,10 +145,10 @@
registerNatives();
}
- private char name[];
- private int priority;
- private Thread threadQ;
- private long eetop;
+ private volatile char name[];
+ private int priority;
+ private Thread threadQ;
+ private long eetop;
/* Whether or not to single_step this thread. */
private boolean single_step;
@@ -1135,7 +1135,7 @@
* @see #getName
* @see #checkAccess()
*/
- public final void setName(String name) {
+ public final synchronized void setName(String name) {
checkAccess();
this.name = name.toCharArray();
if (threadStatus != 0) {
@@ -1150,7 +1150,7 @@
* @see #setName(String)
*/
public final String getName() {
- return String.valueOf(name);
+ return new String(name, true);
}
/**
--- a/jdk/src/share/classes/java/lang/ref/Reference.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/lang/ref/Reference.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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
@@ -138,8 +138,23 @@
pending = r.discovered;
r.discovered = null;
} else {
+ // The waiting on the lock may cause an OOME because it may try to allocate
+ // exception objects, so also catch OOME here to avoid silent exit of the
+ // reference handler thread.
+ //
+ // Explicitly define the order of the two exceptions we catch here
+ // when waiting for the lock.
+ //
+ // We do not want to try to potentially load the InterruptedException class
+ // (which would be done if this was its first use, and InterruptedException
+ // were checked first) in this situation.
+ //
+ // This may lead to the VM not ever trying to load the InterruptedException
+ // class again.
try {
- lock.wait();
+ try {
+ lock.wait();
+ } catch (OutOfMemoryError x) { }
} catch (InterruptedException x) { }
continue;
}
--- a/jdk/src/share/classes/java/lang/reflect/GenericDeclaration.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/lang/reflect/GenericDeclaration.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,7 @@
*
* @since 1.5
*/
-public interface GenericDeclaration {
+public interface GenericDeclaration extends AnnotatedElement {
/**
* Returns an array of {@code TypeVariable} objects that
* represent the type variables declared by the generic
--- a/jdk/src/share/classes/java/nio/charset/Charset-X-Coder.java.template Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/nio/charset/Charset-X-Coder.java.template Mon Jun 03 23:23:20 2013 -0700
@@ -34,6 +34,7 @@
import java.nio.BufferUnderflowException;
import java.lang.ref.WeakReference;
import java.nio.charset.CoderMalfunctionError; // javadoc
+import java.util.Arrays;
/**
@@ -244,7 +245,12 @@
* which is never <tt>null</tt> and is never empty
*/
public final $replType$ replacement() {
+#if[decoder]
return replacement;
+#end[decoder]
+#if[encoder]
+ return Arrays.copyOf(replacement, replacement.$replLength$);
+#end[encoder]
}
/**
@@ -280,12 +286,15 @@
throw new IllegalArgumentException("Empty replacement");
if (len > max$ItypesPerOtype$)
throw new IllegalArgumentException("Replacement too long");
+#if[decoder]
+ this.replacement = newReplacement;
+#end[decoder]
#if[encoder]
if (!isLegalReplacement(newReplacement))
throw new IllegalArgumentException("Illegal replacement");
+ this.replacement = Arrays.copyOf(newReplacement, newReplacement.$replLength$);
#end[encoder]
- this.replacement = newReplacement;
- implReplaceWith(newReplacement);
+ implReplaceWith(this.replacement);
return this;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/nio/file/FileTreeIterator.java Mon Jun 03 23:23:20 2013 -0700
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.nio.file;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.nio.file.FileTreeWalker.Event;
+
+/**
+ * An {@code Iterator to iterate over the nodes of a file tree.
+ *
+ * <pre>{@code
+ * try (FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options)) {
+ * while (iterator.hasNext()) {
+ * Event ev = iterator.next();
+ * Path path = ev.file();
+ * BasicFileAttributes attrs = ev.attributes();
+ * }
+ * }
+ * }</pre>
+ */
+
+class FileTreeIterator implements Iterator<Event>, Closeable {
+ private final FileTreeWalker walker;
+ private Event next;
+
+ /**
+ * Creates a new iterator to walk the file tree starting at the given file.
+ *
+ * @throws IllegalArgumentException
+ * if {@code maxDepth} is negative
+ * @throws IOException
+ * if an I/O errors occurs opening the starting file
+ * @throws SecurityException
+ * if the security manager denies access to the starting file
+ * @throws NullPointerException
+ * if {@code start} or {@code options} is {@ocde null} or
+ * the options array contains a {@code null} element
+ */
+ FileTreeIterator(Path start, int maxDepth, FileVisitOption... options)
+ throws IOException
+ {
+ this.walker = new FileTreeWalker(Arrays.asList(options), maxDepth);
+ this.next = walker.walk(start);
+ assert next.type() == FileTreeWalker.EventType.ENTRY ||
+ next.type() == FileTreeWalker.EventType.START_DIRECTORY;
+
+ // IOException if there a problem accessing the starting file
+ IOException ioe = next.ioeException();
+ if (ioe != null)
+ throw ioe;
+ }
+
+ private void fetchNextIfNeeded() {
+ if (next == null) {
+ FileTreeWalker.Event ev = walker.next();
+ while (ev != null) {
+ IOException ioe = ev.ioeException();
+ if (ioe != null)
+ throw new UncheckedIOException(ioe);
+
+ // END_DIRECTORY events are ignored
+ if (ev.type() != FileTreeWalker.EventType.END_DIRECTORY) {
+ next = ev;
+ return;
+ }
+ ev = walker.next();
+ }
+ }
+ }
+
+ @Override
+ public boolean hasNext() {
+ if (!walker.isOpen())
+ throw new IllegalStateException();
+ fetchNextIfNeeded();
+ return next != null;
+ }
+
+ @Override
+ public Event next() {
+ if (!walker.isOpen())
+ throw new IllegalStateException();
+ fetchNextIfNeeded();
+ if (next == null)
+ throw new NoSuchElementException();
+ Event result = next;
+ next = null;
+ return result;
+ }
+
+ @Override
+ public void close() {
+ walker.close();
+ }
+}
--- a/jdk/src/share/classes/java/nio/file/FileTreeWalker.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/nio/file/FileTreeWalker.java Mon Jun 03 23:23:20 2013 -0700
@@ -29,8 +29,8 @@
import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayDeque;
+import java.util.Collection;
import java.util.Iterator;
-import java.util.Set;
import sun.nio.fs.BasicFileAttributesHolder;
/**
@@ -164,8 +164,17 @@
/**
* Creates a {@code FileTreeWalker}.
+ *
+ * @throws IllegalArgumentException
+ * if {@code maxDepth} is negative
+ * @throws ClassCastException
+ * if (@code options} contains an element that is not a
+ * {@code FileVisitOption}
+ * @throws NullPointerException
+ * if {@code options} is {@ocde null} or the options
+ * array contains a {@code null} element
*/
- FileTreeWalker(Set<FileVisitOption> options, int maxDepth) {
+ FileTreeWalker(Collection<FileVisitOption> options, int maxDepth) {
boolean fl = false;
for (FileVisitOption option: options) {
// will throw NPE if options contains null
@@ -175,6 +184,9 @@
throw new AssertionError("Should not get here");
}
}
+ if (maxDepth < 0)
+ throw new IllegalArgumentException("'maxDepth' is negative");
+
this.followLinks = fl;
this.linkOptions = (fl) ? new LinkOption[0] :
new LinkOption[] { LinkOption.NOFOLLOW_LINKS };
--- a/jdk/src/share/classes/java/nio/file/Files.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/nio/file/Files.java Mon Jun 03 23:23:20 2013 -0700
@@ -25,10 +25,13 @@
package java.nio.file;
+import java.nio.ByteBuffer;
import java.nio.file.attribute.*;
import java.nio.file.spi.FileSystemProvider;
import java.nio.file.spi.FileTypeDetector;
+import java.nio.channels.FileChannel;
import java.nio.channels.SeekableByteChannel;
+import java.io.Closeable;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
@@ -38,7 +41,13 @@
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.IOException;
+import java.io.UncheckedIOException;
import java.util.*;
+import java.util.function.BiPredicate;
+import java.util.stream.CloseableStream;
+import java.util.stream.DelegatingStream;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.nio.charset.Charset;
@@ -2587,9 +2596,6 @@
FileVisitor<? super Path> visitor)
throws IOException
{
- if (maxDepth < 0)
- throw new IllegalArgumentException("'maxDepth' is negative");
-
/**
* Create a FileTreeWalker to walk the file tree, invoking the visitor
* for each event.
@@ -2941,40 +2947,6 @@
}
/**
- * Read all the bytes from an input stream. The {@code initialSize}
- * parameter indicates the initial size of the byte[] to allocate.
- */
- private static byte[] read(InputStream source, int initialSize)
- throws IOException
- {
- int capacity = initialSize;
- byte[] buf = new byte[capacity];
- int nread = 0;
- int rem = buf.length;
- int n;
- // read to EOF which may read more or less than initialSize (eg: file
- // is truncated while we are reading)
- while ((n = source.read(buf, nread, rem)) > 0) {
- nread += n;
- rem -= n;
- assert rem >= 0;
- if (rem == 0) {
- // need larger buffer
- int newCapacity = capacity << 1;
- if (newCapacity < 0) {
- if (capacity == Integer.MAX_VALUE)
- throw new OutOfMemoryError("Required array size too large");
- newCapacity = Integer.MAX_VALUE;
- }
- rem = newCapacity - capacity;
- buf = Arrays.copyOf(buf, newCapacity);
- capacity = newCapacity;
- }
- }
- return (capacity == nread) ? buf : Arrays.copyOf(buf, nread);
- }
-
- /**
* Read all the bytes from a file. The method ensures that the file is
* closed when all bytes have been read or an I/O error, or other runtime
* exception, is thrown.
@@ -2999,12 +2971,22 @@
* method is invoked to check read access to the file.
*/
public static byte[] readAllBytes(Path path) throws IOException {
- long size = size(path);
- if (size > (long)Integer.MAX_VALUE)
- throw new OutOfMemoryError("Required array size too large");
+ try (FileChannel fc = FileChannel.open(path)) {
+ long size = fc.size();
+ if (size > (long)Integer.MAX_VALUE)
+ throw new OutOfMemoryError("Required array size too large");
- try (InputStream in = newInputStream(path)) {
- return read(in, (int)size);
+ byte[] arr = new byte[(int)size];
+ ByteBuffer bb = ByteBuffer.wrap(arr);
+ while (bb.hasRemaining()) {
+ if (fc.read(bb) < 0) {
+ // truncated
+ break;
+ }
+ }
+
+ int nread = bb.position();
+ return (nread == size) ? arr : Arrays.copyOf(arr, nread);
}
}
@@ -3177,4 +3159,336 @@
}
return path;
}
+
+ // -- Stream APIs --
+
+ /**
+ * Implementation of CloseableStream
+ */
+ private static class DelegatingCloseableStream<T> extends DelegatingStream<T>
+ implements CloseableStream<T>
+ {
+ private final Closeable closeable;
+
+ DelegatingCloseableStream(Closeable c, Stream<T> delegate) {
+ super(delegate);
+ this.closeable = c;
+ }
+
+ public void close() {
+ try {
+ closeable.close();
+ } catch (IOException ex) {
+ throw new UncheckedIOException(ex);
+ }
+ }
+ }
+
+ /**
+ * Return a lazily populated {@code CloseableStream}, the elements of
+ * which are the entries in the directory. The listing is not recursive.
+ *
+ * <p> The elements of the stream are {@link Path} objects that are
+ * obtained as if by {@link Path#resolve(Path) resolving} the name of the
+ * directory entry against {@code dir}. Some file systems maintain special
+ * links to the directory itself and the directory's parent directory.
+ * Entries representing these links are not included.
+ *
+ * <p> The stream is <i>weakly consistent</i>. It is thread safe but does
+ * not freeze the directory while iterating, so it may (or may not)
+ * reflect updates to the directory that occur after returning from this
+ * method.
+ *
+ * <p> When not using the try-with-resources construct, then the stream's
+ * {@link CloseableStream#close close} method should be invoked after the
+ * operation is completed so as to free any resources held for the open
+ * directory. Operating on a closed stream behaves as if the end of stream
+ * has been reached. Due to read-ahead, one or more elements may be
+ * returned after the stream has been closed.
+ *
+ * <p> If an {@link IOException} is thrown when accessing the directory
+ * after this method has returned, it is wrapped in an {@link
+ * UncheckedIOException} which will be thrown from the method that caused
+ * the access to take place.
+ *
+ * @param dir The path to the directory
+ *
+ * @return The {@code CloseableStream} describing the content of the
+ * directory
+ *
+ * @throws NotDirectoryException
+ * if the file could not otherwise be opened because it is not
+ * a directory <i>(optional specific exception)</i>
+ * @throws IOException
+ * if an I/O error occurs when opening the directory
+ * @throws SecurityException
+ * In the case of the default provider, and a security manager is
+ * installed, the {@link SecurityManager#checkRead(String) checkRead}
+ * method is invoked to check read access to the directory.
+ *
+ * @see #newDirectoryStream(Path)
+ * @since 1.8
+ */
+ public static CloseableStream<Path> list(Path dir) throws IOException {
+ DirectoryStream<Path> ds = Files.newDirectoryStream(dir);
+ final Iterator<Path> delegate = ds.iterator();
+
+ // Re-wrap DirectoryIteratorException to UncheckedIOException
+ Iterator<Path> it = new Iterator<Path>() {
+ public boolean hasNext() {
+ try {
+ return delegate.hasNext();
+ } catch (DirectoryIteratorException e) {
+ throw new UncheckedIOException(e.getCause());
+ }
+ }
+ public Path next() {
+ try {
+ return delegate.next();
+ } catch (DirectoryIteratorException e) {
+ throw new UncheckedIOException(e.getCause());
+ }
+ }
+ };
+
+ return new DelegatingCloseableStream<>(ds,
+ StreamSupport.stream(Spliterators.spliteratorUnknownSize(it,
+ Spliterator.DISTINCT)));
+ }
+
+ /**
+ * Return a {@code CloseableStream} that is lazily populated with {@code
+ * Path} by walking the file tree rooted at a given starting file. The
+ * file tree is traversed <em>depth-first</em>, the elements in the stream
+ * are {@link Path} objects that are obtained as if by {@link
+ * Path#resolve(Path) resolving} the relative path against {@code start}.
+ *
+ * <p> The {@code stream} walks the file tree as elements are consumed.
+ * The {@code CloseableStream} returned is guaranteed to have at least one
+ * element, the starting file itself. For each file visited, the stream
+ * attempts to read its {@link BasicFileAttributes}. If the file is a
+ * directory and can be opened successfully, entries in the directory, and
+ * their <em>descendants</em> will follow the directory in the stream as
+ * they are encountered. When all entries have been visited, then the
+ * directory is closed. The file tree walk then continues at the next
+ * <em>sibling</em> of the directory.
+ *
+ * <p> The stream is <i>weakly consistent</i>. It does not freeze the
+ * file tree while iterating, so it may (or may not) reflect updates to
+ * the file tree that occur after returned from this method.
+ *
+ * <p> By default, symbolic links are not automatically followed by this
+ * method. If the {@code options} parameter contains the {@link
+ * FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} option then symbolic links are
+ * followed. When following links, and the attributes of the target cannot
+ * be read, then this method attempts to get the {@code BasicFileAttributes}
+ * of the link.
+ *
+ * <p> If the {@code options} parameter contains the {@link
+ * FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} option then the stream keeps
+ * track of directories visited so that cycles can be detected. A cycle
+ * arises when there is an entry in a directory that is an ancestor of the
+ * directory. Cycle detection is done by recording the {@link
+ * java.nio.file.attribute.BasicFileAttributes#fileKey file-key} of directories,
+ * or if file keys are not available, by invoking the {@link #isSameFile
+ * isSameFile} method to test if a directory is the same file as an
+ * ancestor. When a cycle is detected it is treated as an I/O error with
+ * an instance of {@link FileSystemLoopException}.
+ *
+ * <p> The {@code maxDepth} parameter is the maximum number of levels of
+ * directories to visit. A value of {@code 0} means that only the starting
+ * file is visited, unless denied by the security manager. A value of
+ * {@link Integer#MAX_VALUE MAX_VALUE} may be used to indicate that all
+ * levels should be visited.
+ *
+ * <p> When a security manager is installed and it denies access to a file
+ * (or directory), then it is ignored and not included in the stream.
+ *
+ * <p> When not using the try-with-resources construct, then the stream's
+ * {@link CloseableStream#close close} method should be invoked after the
+ * operation is completed so as to free any resources held for the open
+ * directory. Operate the stream after it is closed will throw an
+ * {@link java.lang.IllegalStateException}.
+ *
+ * <p> If an {@link IOException} is thrown when accessing the directory
+ * after this method has returned, it is wrapped in an {@link
+ * UncheckedIOException} which will be thrown from the method that caused
+ * the access to take place.
+ *
+ * @param start
+ * the starting file
+ * @param maxDepth
+ * the maximum number of directory levels to visit
+ * @param options
+ * options to configure the traversal
+ *
+ * @return the {@link CloseableStream} of {@link Path}
+ *
+ * @throws IllegalArgumentException
+ * if the {@code maxDepth} parameter is negative
+ * @throws SecurityException
+ * If the security manager denies access to the starting file.
+ * In the case of the default provider, the {@link
+ * SecurityManager#checkRead(String) checkRead} method is invoked
+ * to check read access to the directory.
+ * @throws IOException
+ * if an I/O error is thrown when accessing the starting file.
+ * @since 1.8
+ */
+ public static CloseableStream<Path> walk(Path start, int maxDepth,
+ FileVisitOption... options)
+ throws IOException
+ {
+ FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
+ return new DelegatingCloseableStream<>(iterator,
+ StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT))
+ .map(entry -> entry.file()));
+ }
+
+ /**
+ * Return a {@code CloseableStream} that is lazily populated with {@code
+ * Path} by walking the file tree rooted at a given starting file. The
+ * file tree is traversed <em>depth-first</em>, the elements in the stream
+ * are {@link Path} objects that are obtained as if by {@link
+ * Path#resolve(Path) resolving} the relative path against {@code start}.
+ *
+ * <p> This method works as if invoking it were equivalent to evaluating the
+ * expression:
+ * <blockquote><pre>
+ * walk(start, Integer.MAX_VALUE, options)
+ * </pre></blockquote>
+ * In other words, it visits all levels of the file tree.
+ *
+ * @param start
+ * the starting file
+ * @param options
+ * options to configure the traversal
+ *
+ * @return the {@link CloseableStream} of {@link Path}
+ *
+ * @throws SecurityException
+ * If the security manager denies access to the starting file.
+ * In the case of the default provider, the {@link
+ * SecurityManager#checkRead(String) checkRead} method is invoked
+ * to check read access to the directory.
+ * @throws IOException
+ * if an I/O error is thrown when accessing the starting file.
+ *
+ * @see #walk(Path, int, FileVisitOption...)
+ * @since 1.8
+ */
+ public static CloseableStream<Path> walk(Path start,
+ FileVisitOption... options)
+ throws IOException
+ {
+ return walk(start, Integer.MAX_VALUE, options);
+ }
+
+ /**
+ * Return a {@code CloseableStream} that is lazily populated with {@code
+ * Path} by searching for files in a file tree rooted at a given starting
+ * file.
+ *
+ * <p> This method walks the file tree in exactly the manner specified by
+ * the {@link #walk walk} method. For each file encountered, the given
+ * {@link BiPredicate} is invoked with its {@link Path} and {@link
+ * BasicFileAttributes}. The {@code Path} object is obtained as if by
+ * {@link Path#resolve(Path) resolving} the relative path against {@code
+ * start} and is only included in the returned {@link CloseableStream} if
+ * the {@code BiPredicate} returns true. Compare to calling {@link
+ * java.util.stream.Stream#filter filter} on the {@code Stream}
+ * returned by {@code walk} method, this method may be more efficient by
+ * avoiding redundant retrieval of the {@code BasicFileAttributes}.
+ *
+ * <p> If an {@link IOException} is thrown when accessing the directory
+ * after returned from this method, it is wrapped in an {@link
+ * UncheckedIOException} which will be thrown from the method that caused
+ * the access to take place.
+ *
+ * @param start
+ * the starting file
+ * @param maxDepth
+ * the maximum number of directory levels to search
+ * @param matcher
+ * the function used to decide whether a file should be included
+ * in the returned stream
+ * @param options
+ * options to configure the traversal
+ *
+ * @return the {@link CloseableStream} of {@link Path}
+ *
+ * @throws IllegalArgumentException
+ * if the {@code maxDepth} parameter is negative
+ * @throws SecurityException
+ * If the security manager denies access to the starting file.
+ * In the case of the default provider, the {@link
+ * SecurityManager#checkRead(String) checkRead} method is invoked
+ * to check read access to the directory.
+ * @throws IOException
+ * if an I/O error is thrown when accessing the starting file.
+ *
+ * @see #walk(Path, int, FileVisitOption...)
+ * @since 1.8
+ */
+ public static CloseableStream<Path> find(Path start,
+ int maxDepth,
+ BiPredicate<Path, BasicFileAttributes> matcher,
+ FileVisitOption... options)
+ throws IOException
+ {
+ FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
+ return new DelegatingCloseableStream<>(iterator,
+ StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT))
+ .filter(entry -> matcher.test(entry.file(), entry.attributes()))
+ .map(entry -> entry.file()));
+ }
+
+ /**
+ * Read all lines from a file as a {@code CloseableStream}. Unlike {@link
+ * #readAllLines(Path, Charset) readAllLines}, this method does not read
+ * all lines into a {@code List}, but instead populates lazily as the stream
+ * is consumed.
+ *
+ * <p> Bytes from the file are decoded into characters using the specified
+ * charset and the same line terminators as specified by {@code
+ * readAllLines} are supported.
+ *
+ * <p> After this method returns, then any subsequent I/O exception that
+ * occurs while reading from the file or when a malformed or unmappable byte
+ * sequence is read, is wrapped in an {@link UncheckedIOException} that will
+ * be thrown form the
+ * {@link java.util.stream.Stream} method that caused the read to take
+ * place. In case an {@code IOException} is thrown when closing the file,
+ * it is also wrapped as an {@code UncheckedIOException}.
+ *
+ * <p> When not using the try-with-resources construct, then stream's
+ * {@link CloseableStream#close close} method should be invoked after
+ * operation is completed so as to free any resources held for the open
+ * file.
+ *
+ * @param path
+ * the path to the file
+ * @param cs
+ * the charset to use for decoding
+ *
+ * @return the lines from the file as a {@code CloseableStream}
+ *
+ * @throws IOException
+ * if an I/O error occurs opening the file
+ * @throws SecurityException
+ * In the case of the default provider, and a security manager is
+ * installed, the {@link SecurityManager#checkRead(String) checkRead}
+ * method is invoked to check read access to the file.
+ *
+ * @see #readAllLines(Path, Charset)
+ * @see #newBufferedReader(Path, Charset)
+ * @see java.io.BufferedReader#lines()
+ * @since 1.8
+ */
+ public static CloseableStream<String> lines(Path path, Charset cs)
+ throws IOException
+ {
+ BufferedReader br = Files.newBufferedReader(path, cs);
+ return new DelegatingCloseableStream<>(br, br.lines());
+ }
}
--- a/jdk/src/share/classes/java/text/DateFormatSymbols.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/text/DateFormatSymbols.java Mon Jun 03 23:23:20 2013 -0700
@@ -59,7 +59,7 @@
* <code>DateFormatSymbols</code> is a public class for encapsulating
* localizable date-time formatting data, such as the names of the
* months, the names of the days of the week, and the time zone data.
- * <code>DateFormat</code> and <code>SimpleDateFormat</code> both use
+ * <code>SimpleDateFormat</code> uses
* <code>DateFormatSymbols</code> to encapsulate this information.
*
* <p>
--- a/jdk/src/share/classes/java/util/Arrays.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/Arrays.java Mon Jun 03 23:23:20 2013 -0700
@@ -40,7 +40,6 @@
import java.util.stream.LongStream;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
-import static java.util.ArraysParallelSortHelpers.*;
/**
* This class contains various methods for manipulating arrays (such as
@@ -70,17 +69,62 @@
public class Arrays {
/**
- * The minimum array length below which the sorting algorithm will not
- * further partition the sorting task.
+ * The minimum array length below which a parallel sorting
+ * algorithm will not further partition the sorting task. Using
+ * smaller sizes typically results in memory contention across
+ * tasks that makes parallel speedups unlikely.
*/
- // reasonable default so that we don't overcreate tasks
- private static final int MIN_ARRAY_SORT_GRAN = 256;
+ private static final int MIN_ARRAY_SORT_GRAN = 1 << 13;
// Suppresses default constructor, ensuring non-instantiability.
private Arrays() {}
+ /**
+ * A comparator that implements the natural ordering of a group of
+ * mutually comparable elements. May be used when a supplied
+ * comparator is null. To simplify code-sharing within underlying
+ * implementations, the compare method only declares type Object
+ * for its second argument.
+ *
+ * Arrays class implementor's note: It is an empirical matter
+ * whether ComparableTimSort offers any performance benefit over
+ * TimSort used with this comparator. If not, you are better off
+ * deleting or bypassing ComparableTimSort. There is currently no
+ * empirical case for separating them for parallel sorting, so all
+ * public Object parallelSort methods use the same comparator
+ * based implementation.
+ */
+ static final class NaturalOrder implements Comparator<Object> {
+ @SuppressWarnings("unchecked")
+ public int compare(Object first, Object second) {
+ return ((Comparable<Object>)first).compareTo(second);
+ }
+ static final NaturalOrder INSTANCE = new NaturalOrder();
+ }
+
+ /**
+ * Checks that {@code fromIndex} and {@code toIndex} are in
+ * the range and throws an exception if they aren't.
+ */
+ private static void rangeCheck(int arrayLength, int fromIndex, int toIndex) {
+ if (fromIndex > toIndex) {
+ throw new IllegalArgumentException(
+ "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
+ }
+ if (fromIndex < 0) {
+ throw new ArrayIndexOutOfBoundsException(fromIndex);
+ }
+ if (toIndex > arrayLength) {
+ throw new ArrayIndexOutOfBoundsException(toIndex);
+ }
+ }
+
/*
- * Sorting of primitive type arrays.
+ * Sorting methods. Note that all public "sort" methods take the
+ * same form: Performing argument checks if necessary, and then
+ * expanding arguments into those required for the internal
+ * implementation methods residing in other package-private
+ * classes (except for legacyMergeSort, included in this class).
*/
/**
@@ -95,7 +139,7 @@
* @param a the array to be sorted
*/
public static void sort(int[] a) {
- DualPivotQuicksort.sort(a);
+ DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
}
/**
@@ -120,7 +164,7 @@
*/
public static void sort(int[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex);
- DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
+ DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
}
/**
@@ -135,7 +179,7 @@
* @param a the array to be sorted
*/
public static void sort(long[] a) {
- DualPivotQuicksort.sort(a);
+ DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
}
/**
@@ -160,7 +204,7 @@
*/
public static void sort(long[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex);
- DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
+ DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
}
/**
@@ -175,7 +219,7 @@
* @param a the array to be sorted
*/
public static void sort(short[] a) {
- DualPivotQuicksort.sort(a);
+ DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
}
/**
@@ -200,7 +244,7 @@
*/
public static void sort(short[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex);
- DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
+ DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
}
/**
@@ -215,7 +259,7 @@
* @param a the array to be sorted
*/
public static void sort(char[] a) {
- DualPivotQuicksort.sort(a);
+ DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
}
/**
@@ -240,7 +284,7 @@
*/
public static void sort(char[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex);
- DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
+ DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
}
/**
@@ -255,7 +299,7 @@
* @param a the array to be sorted
*/
public static void sort(byte[] a) {
- DualPivotQuicksort.sort(a);
+ DualPivotQuicksort.sort(a, 0, a.length - 1);
}
/**
@@ -303,7 +347,7 @@
* @param a the array to be sorted
*/
public static void sort(float[] a) {
- DualPivotQuicksort.sort(a);
+ DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
}
/**
@@ -336,7 +380,7 @@
*/
public static void sort(float[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex);
- DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
+ DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
}
/**
@@ -359,7 +403,7 @@
* @param a the array to be sorted
*/
public static void sort(double[] a) {
- DualPivotQuicksort.sort(a);
+ DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
}
/**
@@ -392,7 +436,742 @@
*/
public static void sort(double[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex);
- DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
+ DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
+ }
+
+ /**
+ * Sorts the specified array into ascending numerical order.
+ *
+ * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+ * array into sub-arrays that are themselves sorted and then merged. When
+ * the sub-array length reaches a minimum granularity, the sub-array is
+ * sorted using the appropriate {@link Arrays#sort(byte[]) Arrays.sort}
+ * method. If the length of the specified array is less than the minimum
+ * granularity, then it is sorted using the appropriate {@link
+ * Arrays#sort(byte[]) Arrays.sort} method. The algorithm requires a
+ * working space no greater than the size of the original array. The
+ * {@link ForkJoinPool#commonPool() ForkJoin common pool} is used to
+ * execute any parallel tasks.
+ *
+ * @param a the array to be sorted
+ *
+ * @since 1.8
+ */
+ public static void parallelSort(byte[] a) {
+ int n = a.length, p, g;
+ if (n <= MIN_ARRAY_SORT_GRAN ||
+ (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+ DualPivotQuicksort.sort(a, 0, n - 1);
+ else
+ new ArraysParallelSortHelpers.FJByte.Sorter
+ (null, a, new byte[n], 0, n, 0,
+ ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+ MIN_ARRAY_SORT_GRAN : g).invoke();
+ }
+
+ /**
+ * Sorts the specified range of the array into ascending numerical order.
+ * The range to be sorted extends from the index {@code fromIndex},
+ * inclusive, to the index {@code toIndex}, exclusive. If
+ * {@code fromIndex == toIndex}, the range to be sorted is empty.
+ *
+ * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+ * array into sub-arrays that are themselves sorted and then merged. When
+ * the sub-array length reaches a minimum granularity, the sub-array is
+ * sorted using the appropriate {@link Arrays#sort(byte[]) Arrays.sort}
+ * method. If the length of the specified array is less than the minimum
+ * granularity, then it is sorted using the appropriate {@link
+ * Arrays#sort(byte[]) Arrays.sort} method. The algorithm requires a working
+ * space no greater than the size of the specified range of the original
+ * array. The {@link ForkJoinPool#commonPool() ForkJoin common pool} is
+ * used to execute any parallel tasks.
+ *
+ * @param a the array to be sorted
+ * @param fromIndex the index of the first element, inclusive, to be sorted
+ * @param toIndex the index of the last element, exclusive, to be sorted
+ *
+ * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code fromIndex < 0} or {@code toIndex > a.length}
+ *
+ * @since 1.8
+ */
+ public static void parallelSort(byte[] a, int fromIndex, int toIndex) {
+ rangeCheck(a.length, fromIndex, toIndex);
+ int n = toIndex - fromIndex, p, g;
+ if (n <= MIN_ARRAY_SORT_GRAN ||
+ (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+ DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
+ else
+ new ArraysParallelSortHelpers.FJByte.Sorter
+ (null, a, new byte[n], fromIndex, n, 0,
+ ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+ MIN_ARRAY_SORT_GRAN : g).invoke();
+ }
+
+ /**
+ * Sorts the specified array into ascending numerical order.
+ *
+ * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+ * array into sub-arrays that are themselves sorted and then merged. When
+ * the sub-array length reaches a minimum granularity, the sub-array is
+ * sorted using the appropriate {@link Arrays#sort(char[]) Arrays.sort}
+ * method. If the length of the specified array is less than the minimum
+ * granularity, then it is sorted using the appropriate {@link
+ * Arrays#sort(char[]) Arrays.sort} method. The algorithm requires a
+ * working space no greater than the size of the original array. The
+ * {@link ForkJoinPool#commonPool() ForkJoin common pool} is used to
+ * execute any parallel tasks.
+ *
+ * @param a the array to be sorted
+ *
+ * @since 1.8
+ */
+ public static void parallelSort(char[] a) {
+ int n = a.length, p, g;
+ if (n <= MIN_ARRAY_SORT_GRAN ||
+ (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+ DualPivotQuicksort.sort(a, 0, n - 1, null, 0, 0);
+ else
+ new ArraysParallelSortHelpers.FJChar.Sorter
+ (null, a, new char[n], 0, n, 0,
+ ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+ MIN_ARRAY_SORT_GRAN : g).invoke();
+ }
+
+ /**
+ * Sorts the specified range of the array into ascending numerical order.
+ * The range to be sorted extends from the index {@code fromIndex},
+ * inclusive, to the index {@code toIndex}, exclusive. If
+ * {@code fromIndex == toIndex}, the range to be sorted is empty.
+ *
+ @implNote The sorting algorithm is a parallel sort-merge that breaks the
+ * array into sub-arrays that are themselves sorted and then merged. When
+ * the sub-array length reaches a minimum granularity, the sub-array is
+ * sorted using the appropriate {@link Arrays#sort(char[]) Arrays.sort}
+ * method. If the length of the specified array is less than the minimum
+ * granularity, then it is sorted using the appropriate {@link
+ * Arrays#sort(char[]) Arrays.sort} method. The algorithm requires a working
+ * space no greater than the size of the specified range of the original
+ * array. The {@link ForkJoinPool#commonPool() ForkJoin common pool} is
+ * used to execute any parallel tasks.
+ *
+ * @param a the array to be sorted
+ * @param fromIndex the index of the first element, inclusive, to be sorted
+ * @param toIndex the index of the last element, exclusive, to be sorted
+ *
+ * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code fromIndex < 0} or {@code toIndex > a.length}
+ *
+ * @since 1.8
+ */
+ public static void parallelSort(char[] a, int fromIndex, int toIndex) {
+ rangeCheck(a.length, fromIndex, toIndex);
+ int n = toIndex - fromIndex, p, g;
+ if (n <= MIN_ARRAY_SORT_GRAN ||
+ (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+ DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
+ else
+ new ArraysParallelSortHelpers.FJChar.Sorter
+ (null, a, new char[n], fromIndex, n, 0,
+ ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+ MIN_ARRAY_SORT_GRAN : g).invoke();
+ }
+
+ /**
+ * Sorts the specified array into ascending numerical order.
+ *
+ * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+ * array into sub-arrays that are themselves sorted and then merged. When
+ * the sub-array length reaches a minimum granularity, the sub-array is
+ * sorted using the appropriate {@link Arrays#sort(short[]) Arrays.sort}
+ * method. If the length of the specified array is less than the minimum
+ * granularity, then it is sorted using the appropriate {@link
+ * Arrays#sort(short[]) Arrays.sort} method. The algorithm requires a
+ * working space no greater than the size of the original array. The
+ * {@link ForkJoinPool#commonPool() ForkJoin common pool} is used to
+ * execute any parallel tasks.
+ *
+ * @param a the array to be sorted
+ *
+ * @since 1.8
+ */
+ public static void parallelSort(short[] a) {
+ int n = a.length, p, g;
+ if (n <= MIN_ARRAY_SORT_GRAN ||
+ (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+ DualPivotQuicksort.sort(a, 0, n - 1, null, 0, 0);
+ else
+ new ArraysParallelSortHelpers.FJShort.Sorter
+ (null, a, new short[n], 0, n, 0,
+ ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+ MIN_ARRAY_SORT_GRAN : g).invoke();
+ }
+
+ /**
+ * Sorts the specified range of the array into ascending numerical order.
+ * The range to be sorted extends from the index {@code fromIndex},
+ * inclusive, to the index {@code toIndex}, exclusive. If
+ * {@code fromIndex == toIndex}, the range to be sorted is empty.
+ *
+ * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+ * array into sub-arrays that are themselves sorted and then merged. When
+ * the sub-array length reaches a minimum granularity, the sub-array is
+ * sorted using the appropriate {@link Arrays#sort(short[]) Arrays.sort}
+ * method. If the length of the specified array is less than the minimum
+ * granularity, then it is sorted using the appropriate {@link
+ * Arrays#sort(short[]) Arrays.sort} method. The algorithm requires a working
+ * space no greater than the size of the specified range of the original
+ * array. The {@link ForkJoinPool#commonPool() ForkJoin common pool} is
+ * used to execute any parallel tasks.
+ *
+ * @param a the array to be sorted
+ * @param fromIndex the index of the first element, inclusive, to be sorted
+ * @param toIndex the index of the last element, exclusive, to be sorted
+ *
+ * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code fromIndex < 0} or {@code toIndex > a.length}
+ *
+ * @since 1.8
+ */
+ public static void parallelSort(short[] a, int fromIndex, int toIndex) {
+ rangeCheck(a.length, fromIndex, toIndex);
+ int n = toIndex - fromIndex, p, g;
+ if (n <= MIN_ARRAY_SORT_GRAN ||
+ (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+ DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
+ else
+ new ArraysParallelSortHelpers.FJShort.Sorter
+ (null, a, new short[n], fromIndex, n, 0,
+ ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+ MIN_ARRAY_SORT_GRAN : g).invoke();
+ }
+
+ /**
+ * Sorts the specified array into ascending numerical order.
+ *
+ * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+ * array into sub-arrays that are themselves sorted and then merged. When
+ * the sub-array length reaches a minimum granularity, the sub-array is
+ * sorted using the appropriate {@link Arrays#sort(int[]) Arrays.sort}
+ * method. If the length of the specified array is less than the minimum
+ * granularity, then it is sorted using the appropriate {@link
+ * Arrays#sort(int[]) Arrays.sort} method. The algorithm requires a
+ * working space no greater than the size of the original array. The
+ * {@link ForkJoinPool#commonPool() ForkJoin common pool} is used to
+ * execute any parallel tasks.
+ *
+ * @param a the array to be sorted
+ *
+ * @since 1.8
+ */
+ public static void parallelSort(int[] a) {
+ int n = a.length, p, g;
+ if (n <= MIN_ARRAY_SORT_GRAN ||
+ (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+ DualPivotQuicksort.sort(a, 0, n - 1, null, 0, 0);
+ else
+ new ArraysParallelSortHelpers.FJInt.Sorter
+ (null, a, new int[n], 0, n, 0,
+ ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+ MIN_ARRAY_SORT_GRAN : g).invoke();
+ }
+
+ /**
+ * Sorts the specified range of the array into ascending numerical order.
+ * The range to be sorted extends from the index {@code fromIndex},
+ * inclusive, to the index {@code toIndex}, exclusive. If
+ * {@code fromIndex == toIndex}, the range to be sorted is empty.
+ *
+ * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+ * array into sub-arrays that are themselves sorted and then merged. When
+ * the sub-array length reaches a minimum granularity, the sub-array is
+ * sorted using the appropriate {@link Arrays#sort(int[]) Arrays.sort}
+ * method. If the length of the specified array is less than the minimum
+ * granularity, then it is sorted using the appropriate {@link
+ * Arrays#sort(int[]) Arrays.sort} method. The algorithm requires a working
+ * space no greater than the size of the specified range of the original
+ * array. The {@link ForkJoinPool#commonPool() ForkJoin common pool} is
+ * used to execute any parallel tasks.
+ *
+ * @param a the array to be sorted
+ * @param fromIndex the index of the first element, inclusive, to be sorted
+ * @param toIndex the index of the last element, exclusive, to be sorted
+ *
+ * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code fromIndex < 0} or {@code toIndex > a.length}
+ *
+ * @since 1.8
+ */
+ public static void parallelSort(int[] a, int fromIndex, int toIndex) {
+ rangeCheck(a.length, fromIndex, toIndex);
+ int n = toIndex - fromIndex, p, g;
+ if (n <= MIN_ARRAY_SORT_GRAN ||
+ (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+ DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
+ else
+ new ArraysParallelSortHelpers.FJInt.Sorter
+ (null, a, new int[n], fromIndex, n, 0,
+ ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+ MIN_ARRAY_SORT_GRAN : g).invoke();
+ }
+
+ /**
+ * Sorts the specified array into ascending numerical order.
+ *
+ * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+ * array into sub-arrays that are themselves sorted and then merged. When
+ * the sub-array length reaches a minimum granularity, the sub-array is
+ * sorted using the appropriate {@link Arrays#sort(long[]) Arrays.sort}
+ * method. If the length of the specified array is less than the minimum
+ * granularity, then it is sorted using the appropriate {@link
+ * Arrays#sort(long[]) Arrays.sort} method. The algorithm requires a
+ * working space no greater than the size of the original array. The
+ * {@link ForkJoinPool#commonPool() ForkJoin common pool} is used to
+ * execute any parallel tasks.
+ *
+ * @param a the array to be sorted
+ *
+ * @since 1.8
+ */
+ public static void parallelSort(long[] a) {
+ int n = a.length, p, g;
+ if (n <= MIN_ARRAY_SORT_GRAN ||
+ (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+ DualPivotQuicksort.sort(a, 0, n - 1, null, 0, 0);
+ else
+ new ArraysParallelSortHelpers.FJLong.Sorter
+ (null, a, new long[n], 0, n, 0,
+ ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+ MIN_ARRAY_SORT_GRAN : g).invoke();
+ }
+
+ /**
+ * Sorts the specified range of the array into ascending numerical order.
+ * The range to be sorted extends from the index {@code fromIndex},
+ * inclusive, to the index {@code toIndex}, exclusive. If
+ * {@code fromIndex == toIndex}, the range to be sorted is empty.
+ *
+ * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+ * array into sub-arrays that are themselves sorted and then merged. When
+ * the sub-array length reaches a minimum granularity, the sub-array is
+ * sorted using the appropriate {@link Arrays#sort(long[]) Arrays.sort}
+ * method. If the length of the specified array is less than the minimum
+ * granularity, then it is sorted using the appropriate {@link
+ * Arrays#sort(long[]) Arrays.sort} method. The algorithm requires a working
+ * space no greater than the size of the specified range of the original
+ * array. The {@link ForkJoinPool#commonPool() ForkJoin common pool} is
+ * used to execute any parallel tasks.
+ *
+ * @param a the array to be sorted
+ * @param fromIndex the index of the first element, inclusive, to be sorted
+ * @param toIndex the index of the last element, exclusive, to be sorted
+ *
+ * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code fromIndex < 0} or {@code toIndex > a.length}
+ *
+ * @since 1.8
+ */
+ public static void parallelSort(long[] a, int fromIndex, int toIndex) {
+ rangeCheck(a.length, fromIndex, toIndex);
+ int n = toIndex - fromIndex, p, g;
+ if (n <= MIN_ARRAY_SORT_GRAN ||
+ (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+ DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
+ else
+ new ArraysParallelSortHelpers.FJLong.Sorter
+ (null, a, new long[n], fromIndex, n, 0,
+ ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+ MIN_ARRAY_SORT_GRAN : g).invoke();
+ }
+
+ /**
+ * Sorts the specified array into ascending numerical order.
+ *
+ * <p>The {@code <} relation does not provide a total order on all float
+ * values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
+ * value compares neither less than, greater than, nor equal to any value,
+ * even itself. This method uses the total order imposed by the method
+ * {@link Float#compareTo}: {@code -0.0f} is treated as less than value
+ * {@code 0.0f} and {@code Float.NaN} is considered greater than any
+ * other value and all {@code Float.NaN} values are considered equal.
+ *
+ * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+ * array into sub-arrays that are themselves sorted and then merged. When
+ * the sub-array length reaches a minimum granularity, the sub-array is
+ * sorted using the appropriate {@link Arrays#sort(float[]) Arrays.sort}
+ * method. If the length of the specified array is less than the minimum
+ * granularity, then it is sorted using the appropriate {@link
+ * Arrays#sort(float[]) Arrays.sort} method. The algorithm requires a
+ * working space no greater than the size of the original array. The
+ * {@link ForkJoinPool#commonPool() ForkJoin common pool} is used to
+ * execute any parallel tasks.
+ *
+ * @param a the array to be sorted
+ *
+ * @since 1.8
+ */
+ public static void parallelSort(float[] a) {
+ int n = a.length, p, g;
+ if (n <= MIN_ARRAY_SORT_GRAN ||
+ (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+ DualPivotQuicksort.sort(a, 0, n - 1, null, 0, 0);
+ else
+ new ArraysParallelSortHelpers.FJFloat.Sorter
+ (null, a, new float[n], 0, n, 0,
+ ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+ MIN_ARRAY_SORT_GRAN : g).invoke();
+ }
+
+ /**
+ * Sorts the specified range of the array into ascending numerical order.
+ * The range to be sorted extends from the index {@code fromIndex},
+ * inclusive, to the index {@code toIndex}, exclusive. If
+ * {@code fromIndex == toIndex}, the range to be sorted is empty.
+ *
+ * <p>The {@code <} relation does not provide a total order on all float
+ * values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
+ * value compares neither less than, greater than, nor equal to any value,
+ * even itself. This method uses the total order imposed by the method
+ * {@link Float#compareTo}: {@code -0.0f} is treated as less than value
+ * {@code 0.0f} and {@code Float.NaN} is considered greater than any
+ * other value and all {@code Float.NaN} values are considered equal.
+ *
+ * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+ * array into sub-arrays that are themselves sorted and then merged. When
+ * the sub-array length reaches a minimum granularity, the sub-array is
+ * sorted using the appropriate {@link Arrays#sort(float[]) Arrays.sort}
+ * method. If the length of the specified array is less than the minimum
+ * granularity, then it is sorted using the appropriate {@link
+ * Arrays#sort(float[]) Arrays.sort} method. The algorithm requires a working
+ * space no greater than the size of the specified range of the original
+ * array. The {@link ForkJoinPool#commonPool() ForkJoin common pool} is
+ * used to execute any parallel tasks.
+ *
+ * @param a the array to be sorted
+ * @param fromIndex the index of the first element, inclusive, to be sorted
+ * @param toIndex the index of the last element, exclusive, to be sorted
+ *
+ * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code fromIndex < 0} or {@code toIndex > a.length}
+ *
+ * @since 1.8
+ */
+ public static void parallelSort(float[] a, int fromIndex, int toIndex) {
+ rangeCheck(a.length, fromIndex, toIndex);
+ int n = toIndex - fromIndex, p, g;
+ if (n <= MIN_ARRAY_SORT_GRAN ||
+ (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+ DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
+ else
+ new ArraysParallelSortHelpers.FJFloat.Sorter
+ (null, a, new float[n], fromIndex, n, 0,
+ ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+ MIN_ARRAY_SORT_GRAN : g).invoke();
+ }
+
+ /**
+ * Sorts the specified array into ascending numerical order.
+ *
+ * <p>The {@code <} relation does not provide a total order on all double
+ * values: {@code -0.0d == 0.0d} is {@code true} and a {@code Double.NaN}
+ * value compares neither less than, greater than, nor equal to any value,
+ * even itself. This method uses the total order imposed by the method
+ * {@link Double#compareTo}: {@code -0.0d} is treated as less than value
+ * {@code 0.0d} and {@code Double.NaN} is considered greater than any
+ * other value and all {@code Double.NaN} values are considered equal.
+ *
+ * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+ * array into sub-arrays that are themselves sorted and then merged. When
+ * the sub-array length reaches a minimum granularity, the sub-array is
+ * sorted using the appropriate {@link Arrays#sort(double[]) Arrays.sort}
+ * method. If the length of the specified array is less than the minimum
+ * granularity, then it is sorted using the appropriate {@link
+ * Arrays#sort(double[]) Arrays.sort} method. The algorithm requires a
+ * working space no greater than the size of the original array. The
+ * {@link ForkJoinPool#commonPool() ForkJoin common pool} is used to
+ * execute any parallel tasks.
+ *
+ * @param a the array to be sorted
+ *
+ * @since 1.8
+ */
+ public static void parallelSort(double[] a) {
+ int n = a.length, p, g;
+ if (n <= MIN_ARRAY_SORT_GRAN ||
+ (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+ DualPivotQuicksort.sort(a, 0, n - 1, null, 0, 0);
+ else
+ new ArraysParallelSortHelpers.FJDouble.Sorter
+ (null, a, new double[n], 0, n, 0,
+ ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+ MIN_ARRAY_SORT_GRAN : g).invoke();
+ }
+
+ /**
+ * Sorts the specified range of the array into ascending numerical order.
+ * The range to be sorted extends from the index {@code fromIndex},
+ * inclusive, to the index {@code toIndex}, exclusive. If
+ * {@code fromIndex == toIndex}, the range to be sorted is empty.
+ *
+ * <p>The {@code <} relation does not provide a total order on all double
+ * values: {@code -0.0d == 0.0d} is {@code true} and a {@code Double.NaN}
+ * value compares neither less than, greater than, nor equal to any value,
+ * even itself. This method uses the total order imposed by the method
+ * {@link Double#compareTo}: {@code -0.0d} is treated as less than value
+ * {@code 0.0d} and {@code Double.NaN} is considered greater than any
+ * other value and all {@code Double.NaN} values are considered equal.
+ *
+ * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+ * array into sub-arrays that are themselves sorted and then merged. When
+ * the sub-array length reaches a minimum granularity, the sub-array is
+ * sorted using the appropriate {@link Arrays#sort(double[]) Arrays.sort}
+ * method. If the length of the specified array is less than the minimum
+ * granularity, then it is sorted using the appropriate {@link
+ * Arrays#sort(double[]) Arrays.sort} method. The algorithm requires a working
+ * space no greater than the size of the specified range of the original
+ * array. The {@link ForkJoinPool#commonPool() ForkJoin common pool} is
+ * used to execute any parallel tasks.
+ *
+ * @param a the array to be sorted
+ * @param fromIndex the index of the first element, inclusive, to be sorted
+ * @param toIndex the index of the last element, exclusive, to be sorted
+ *
+ * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+ * @throws ArrayIndexOutOfBoundsException
+ * if {@code fromIndex < 0} or {@code toIndex > a.length}
+ *
+ * @since 1.8
+ */
+ public static void parallelSort(double[] a, int fromIndex, int toIndex) {
+ rangeCheck(a.length, fromIndex, toIndex);
+ int n = toIndex - fromIndex, p, g;
+ if (n <= MIN_ARRAY_SORT_GRAN ||
+ (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+ DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
+ else
+ new ArraysParallelSortHelpers.FJDouble.Sorter
+ (null, a, new double[n], fromIndex, n, 0,
+ ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+ MIN_ARRAY_SORT_GRAN : g).invoke();
+ }
+
+ /**
+ * Sorts the specified array of objects into ascending order, according
+ * to the {@linkplain Comparable natural ordering} of its elements.
+ * All elements in the array must implement the {@link Comparable}
+ * interface. Furthermore, all elements in the array must be
+ * <i>mutually comparable</i> (that is, {@code e1.compareTo(e2)} must
+ * not throw a {@code ClassCastException} for any elements {@code e1}
+ * and {@code e2} in the array).
+ *
+ * <p>This sort is guaranteed to be <i>stable</i>: equal elements will
+ * not be reordered as a result of the sort.
+ *
+ * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+ * array into sub-arrays that are themselves sorted and then merged. When
+ * the sub-array length reaches a minimum granularity, the sub-array is
+ * sorted using the appropriate {@link Arrays#sort(Object[]) Arrays.sort}
+ * method. If the length of the specified array is less than the minimum
+ * granularity, then it is sorted using the appropriate {@link
+ * Arrays#sort(Object[]) Arrays.sort} method. The algorithm requires a
+ * working space no greater than the size of the original array. The
+ * {@link ForkJoinPool#commonPool() ForkJoin common pool} is used to
+ * execute any parallel tasks.
+ *
+ * @param a the array to be sorted
+ *
+ * @throws ClassCastException if the array contains elements that are not
+ * <i>mutually comparable</i> (for example, strings and integers)
+ * @throws IllegalArgumentException (optional) if the natural
+ * ordering of the array elements is found to violate the
+ * {@link Comparable} contract
+ *
+ * @since 1.8
+ */
+ @SuppressWarnings("unchecked")
+ public static <T extends Comparable<? super T>> void parallelSort(T[] a) {
+ int n = a.length, p, g;
+ if (n <= MIN_ARRAY_SORT_GRAN ||
+ (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+ TimSort.sort(a, 0, n, NaturalOrder.INSTANCE, null, 0, 0);
+ else
+ new ArraysParallelSortHelpers.FJObject.Sorter<T>
+ (null, a,
+ (T[])Array.newInstance(a.getClass().getComponentType(), n),
+ 0, n, 0, ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+ MIN_ARRAY_SORT_GRAN : g, NaturalOrder.INSTANCE).invoke();
+ }
+
+ /**
+ * Sorts the specified range of the specified array of objects into
+ * ascending order, according to the
+ * {@linkplain Comparable natural ordering} of its
+ * elements. The range to be sorted extends from index
+ * {@code fromIndex}, inclusive, to index {@code toIndex}, exclusive.
+ * (If {@code fromIndex==toIndex}, the range to be sorted is empty.) All
+ * elements in this range must implement the {@link Comparable}
+ * interface. Furthermore, all elements in this range must be <i>mutually
+ * comparable</i> (that is, {@code e1.compareTo(e2)} must not throw a
+ * {@code ClassCastException} for any elements {@code e1} and
+ * {@code e2} in the array).
+ *
+ * <p>This sort is guaranteed to be <i>stable</i>: equal elements will
+ * not be reordered as a result of the sort.
+ *
+ * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+ * array into sub-arrays that are themselves sorted and then merged. When
+ * the sub-array length reaches a minimum granularity, the sub-array is
+ * sorted using the appropriate {@link Arrays#sort(Object[]) Arrays.sort}
+ * method. If the length of the specified array is less than the minimum
+ * granularity, then it is sorted using the appropriate {@link
+ * Arrays#sort(Object[]) Arrays.sort} method. The algorithm requires a working
+ * space no greater than the size of the specified range of the original
+ * array. The {@link ForkJoinPool#commonPool() ForkJoin common pool} is
+ * used to execute any parallel tasks.
+ *
+ * @param a the array to be sorted
+ * @param fromIndex the index of the first element (inclusive) to be
+ * sorted
+ * @param toIndex the index of the last element (exclusive) to be sorted
+ * @throws IllegalArgumentException if {@code fromIndex > toIndex} or
+ * (optional) if the natural ordering of the array elements is
+ * found to violate the {@link Comparable} contract
+ * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or
+ * {@code toIndex > a.length}
+ * @throws ClassCastException if the array contains elements that are
+ * not <i>mutually comparable</i> (for example, strings and
+ * integers).
+ *
+ * @since 1.8
+ */
+ @SuppressWarnings("unchecked")
+ public static <T extends Comparable<? super T>>
+ void parallelSort(T[] a, int fromIndex, int toIndex) {
+ rangeCheck(a.length, fromIndex, toIndex);
+ int n = toIndex - fromIndex, p, g;
+ if (n <= MIN_ARRAY_SORT_GRAN ||
+ (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+ TimSort.sort(a, fromIndex, toIndex, NaturalOrder.INSTANCE, null, 0, 0);
+ else
+ new ArraysParallelSortHelpers.FJObject.Sorter<T>
+ (null, a,
+ (T[])Array.newInstance(a.getClass().getComponentType(), n),
+ fromIndex, n, 0, ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+ MIN_ARRAY_SORT_GRAN : g, NaturalOrder.INSTANCE).invoke();
+ }
+
+ /**
+ * Sorts the specified array of objects according to the order induced by
+ * the specified comparator. All elements in the array must be
+ * <i>mutually comparable</i> by the specified comparator (that is,
+ * {@code c.compare(e1, e2)} must not throw a {@code ClassCastException}
+ * for any elements {@code e1} and {@code e2} in the array).
+ *
+ * <p>This sort is guaranteed to be <i>stable</i>: equal elements will
+ * not be reordered as a result of the sort.
+ *
+ * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+ * array into sub-arrays that are themselves sorted and then merged. When
+ * the sub-array length reaches a minimum granularity, the sub-array is
+ * sorted using the appropriate {@link Arrays#sort(Object[]) Arrays.sort}
+ * method. If the length of the specified array is less than the minimum
+ * granularity, then it is sorted using the appropriate {@link
+ * Arrays#sort(Object[]) Arrays.sort} method. The algorithm requires a
+ * working space no greater than the size of the original array. The
+ * {@link ForkJoinPool#commonPool() ForkJoin common pool} is used to
+ * execute any parallel tasks.
+ *
+ * @param a the array to be sorted
+ * @param cmp the comparator to determine the order of the array. A
+ * {@code null} value indicates that the elements'
+ * {@linkplain Comparable natural ordering} should be used.
+ * @throws ClassCastException if the array contains elements that are
+ * not <i>mutually comparable</i> using the specified comparator
+ * @throws IllegalArgumentException (optional) if the comparator is
+ * found to violate the {@link java.util.Comparator} contract
+ *
+ * @since 1.8
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> void parallelSort(T[] a, Comparator<? super T> cmp) {
+ if (cmp == null)
+ cmp = NaturalOrder.INSTANCE;
+ int n = a.length, p, g;
+ if (n <= MIN_ARRAY_SORT_GRAN ||
+ (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+ TimSort.sort(a, 0, n, cmp, null, 0, 0);
+ else
+ new ArraysParallelSortHelpers.FJObject.Sorter<T>
+ (null, a,
+ (T[])Array.newInstance(a.getClass().getComponentType(), n),
+ 0, n, 0, ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+ MIN_ARRAY_SORT_GRAN : g, cmp).invoke();
+ }
+
+ /**
+ * Sorts the specified range of the specified array of objects according
+ * to the order induced by the specified comparator. The range to be
+ * sorted extends from index {@code fromIndex}, inclusive, to index
+ * {@code toIndex}, exclusive. (If {@code fromIndex==toIndex}, the
+ * range to be sorted is empty.) All elements in the range must be
+ * <i>mutually comparable</i> by the specified comparator (that is,
+ * {@code c.compare(e1, e2)} must not throw a {@code ClassCastException}
+ * for any elements {@code e1} and {@code e2} in the range).
+ *
+ * <p>This sort is guaranteed to be <i>stable</i>: equal elements will
+ * not be reordered as a result of the sort.
+ *
+ * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+ * array into sub-arrays that are themselves sorted and then merged. When
+ * the sub-array length reaches a minimum granularity, the sub-array is
+ * sorted using the appropriate {@link Arrays#sort(Object[]) Arrays.sort}
+ * method. If the length of the specified array is less than the minimum
+ * granularity, then it is sorted using the appropriate {@link
+ * Arrays#sort(Object[]) Arrays.sort} method. The algorithm requires a working
+ * space no greater than the size of the specified range of the original
+ * array. The {@link ForkJoinPool#commonPool() ForkJoin common pool} is
+ * used to execute any parallel tasks.
+ *
+ * @param a the array to be sorted
+ * @param fromIndex the index of the first element (inclusive) to be
+ * sorted
+ * @param toIndex the index of the last element (exclusive) to be sorted
+ * @param cmp the comparator to determine the order of the array. A
+ * {@code null} value indicates that the elements'
+ * {@linkplain Comparable natural ordering} should be used.
+ * @throws IllegalArgumentException if {@code fromIndex > toIndex} or
+ * (optional) if the natural ordering of the array elements is
+ * found to violate the {@link Comparable} contract
+ * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or
+ * {@code toIndex > a.length}
+ * @throws ClassCastException if the array contains elements that are
+ * not <i>mutually comparable</i> (for example, strings and
+ * integers).
+ *
+ * @since 1.8
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> void parallelSort(T[] a, int fromIndex, int toIndex,
+ Comparator<? super T> cmp) {
+ rangeCheck(a.length, fromIndex, toIndex);
+ if (cmp == null)
+ cmp = NaturalOrder.INSTANCE;
+ int n = toIndex - fromIndex, p, g;
+ if (n <= MIN_ARRAY_SORT_GRAN ||
+ (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+ TimSort.sort(a, fromIndex, toIndex, cmp, null, 0, 0);
+ else
+ new ArraysParallelSortHelpers.FJObject.Sorter<T>
+ (null, a,
+ (T[])Array.newInstance(a.getClass().getComponentType(), n),
+ fromIndex, n, 0, ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+ MIN_ARRAY_SORT_GRAN : g, cmp).invoke();
}
/*
@@ -412,39 +1191,6 @@
"java.util.Arrays.useLegacyMergeSort")).booleanValue();
}
- /*
- * If this platform has an optimizing VM, check whether ComparableTimSort
- * offers any performance benefit over TimSort in conjunction with a
- * comparator that returns:
- * {@code ((Comparable)first).compareTo(Second)}.
- * If not, you are better off deleting ComparableTimSort to
- * eliminate the code duplication. In other words, the commented
- * out code below is the preferable implementation for sorting
- * arrays of Comparables if it offers sufficient performance.
- */
-
-// /**
-// * A comparator that implements the natural ordering of a group of
-// * mutually comparable elements. Using this comparator saves us
-// * from duplicating most of the code in this file (one version for
-// * Comparables, one for explicit Comparators).
-// */
-// private static final Comparator<Object> NATURAL_ORDER =
-// new Comparator<Object>() {
-// @SuppressWarnings("unchecked")
-// public int compare(Object first, Object second) {
-// return ((Comparable<Object>)first).compareTo(second);
-// }
-// };
-//
-// public static void sort(Object[] a) {
-// sort(a, 0, a.length, NATURAL_ORDER);
-// }
-//
-// public static void sort(Object[] a, int fromIndex, int toIndex) {
-// sort(a, fromIndex, toIndex, NATURAL_ORDER);
-// }
-
/**
* Sorts the specified array of objects into ascending order, according
* to the {@linkplain Comparable natural ordering} of its elements.
@@ -491,7 +1237,7 @@
if (LegacyMergeSort.userRequested)
legacyMergeSort(a);
else
- ComparableTimSort.sort(a);
+ ComparableTimSort.sort(a, 0, a.length, null, 0, 0);
}
/** To be removed in a future release. */
@@ -553,16 +1299,16 @@
* integers).
*/
public static void sort(Object[] a, int fromIndex, int toIndex) {
+ rangeCheck(a.length, fromIndex, toIndex);
if (LegacyMergeSort.userRequested)
legacyMergeSort(a, fromIndex, toIndex);
else
- ComparableTimSort.sort(a, fromIndex, toIndex);
+ ComparableTimSort.sort(a, fromIndex, toIndex, null, 0, 0);
}
/** To be removed in a future release. */
private static void legacyMergeSort(Object[] a,
int fromIndex, int toIndex) {
- rangeCheck(a.length, fromIndex, toIndex);
Object[] aux = copyOfRange(a, fromIndex, toIndex);
mergeSort(aux, a, fromIndex, toIndex, -fromIndex);
}
@@ -676,10 +1422,12 @@
* found to violate the {@link Comparator} contract
*/
public static <T> void sort(T[] a, Comparator<? super T> c) {
+ if (c == null)
+ c = NaturalOrder.INSTANCE;
if (LegacyMergeSort.userRequested)
legacyMergeSort(a, c);
else
- TimSort.sort(a, c);
+ TimSort.sort(a, 0, a.length, c, null, 0, 0);
}
/** To be removed in a future release. */
@@ -744,16 +1492,18 @@
*/
public static <T> void sort(T[] a, int fromIndex, int toIndex,
Comparator<? super T> c) {
+ if (c == null)
+ c = NaturalOrder.INSTANCE;
+ rangeCheck(a.length, fromIndex, toIndex);
if (LegacyMergeSort.userRequested)
legacyMergeSort(a, fromIndex, toIndex, c);
else
- TimSort.sort(a, fromIndex, toIndex, c);
+ TimSort.sort(a, fromIndex, toIndex, c, null, 0, 0);
}
/** To be removed in a future release. */
private static <T> void legacyMergeSort(T[] a, int fromIndex, int toIndex,
Comparator<? super T> c) {
- rangeCheck(a.length, fromIndex, toIndex);
T[] aux = copyOfRange(a, fromIndex, toIndex);
if (c==null)
mergeSort(aux, a, fromIndex, toIndex, -fromIndex);
@@ -809,630 +1559,6 @@
}
}
- /*
- * Parallel sorting of primitive type arrays.
- */
-
- /**
- * Sorts the specified array into ascending numerical order.
- *
- * <p>Implementation note: The sorting algorithm is a parallel sort-merge
- * that breaks the array into sub-arrays that are themselves sorted and then
- * merged. When the sub-array length reaches a minimum granularity, the
- * sub-array is sorted using the appropriate {@link Arrays#sort(byte[])
- * Arrays.sort} method. The algorithm requires a working space equal to the
- * size of the original array. The {@link
- * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
- * used to execute any parallel tasks.
- *
- * @param a the array to be sorted
- *
- * @since 1.8
- */
- public static void parallelSort(byte[] a) {
- parallelSort(a, 0, a.length);
- }
-
- /**
- * Sorts the specified range of the array into ascending order. The range
- * to be sorted extends from the index {@code fromIndex}, inclusive, to
- * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
- * the range to be sorted is empty.
- *
- * <p>Implementation note: The sorting algorithm is a parallel sort-merge
- * that breaks the array into sub-arrays that are themselves sorted and then
- * merged. When the sub-array length reaches a minimum granularity, the
- * sub-array is sorted using the appropriate {@link Arrays#sort(byte[])
- * Arrays.sort} method. The algorithm requires a working space equal to the
- * size of the original array. The {@link
- * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
- * used to execute any parallel tasks.
- *
- * @param a the array to be sorted
- * @param fromIndex the index of the first element, inclusive, to be sorted
- * @param toIndex the index of the last element, exclusive, to be sorted
- *
- * @throws IllegalArgumentException if {@code fromIndex > toIndex}
- * @throws ArrayIndexOutOfBoundsException
- * if {@code fromIndex < 0} or {@code toIndex > a.length}
- *
- * @since 1.8
- */
- public static void parallelSort(byte[] a, int fromIndex, int toIndex) {
- rangeCheck(a.length, fromIndex, toIndex);
- int nelements = toIndex - fromIndex;
- int gran = getSplitThreshold(nelements);
- FJByte.Sorter task = new FJByte.Sorter(a, new byte[a.length], fromIndex,
- nelements, gran);
- task.invoke();
- }
-
- /**
- * Sorts the specified array into ascending numerical order.
- *
- * <p>Implementation note: The sorting algorithm is a parallel sort-merge
- * that breaks the array into sub-arrays that are themselves sorted and then
- * merged. When the sub-array length reaches a minimum granularity, the
- * sub-array is sorted using the appropriate {@link Arrays#sort(char[])
- * Arrays.sort} method. The algorithm requires a working space equal to the
- * size of the original array. The {@link
- * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
- * used to execute any parallel tasks.
- *
- * @param a the array to be sorted
- *
- * @since 1.8
- */
- public static void parallelSort(char[] a) {
- parallelSort(a, 0, a.length);
- }
-
- /**
- * Sorts the specified range of the array into ascending order. The range
- * to be sorted extends from the index {@code fromIndex}, inclusive, to
- * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
- * the range to be sorted is empty.
- *
- * <p>Implementation note: The sorting algorithm is a parallel sort-merge
- * that breaks the array into sub-arrays that are themselves sorted and then
- * merged. When the sub-array length reaches a minimum granularity, the
- * sub-array is sorted using the appropriate {@link Arrays#sort(char[])
- * Arrays.sort} method. The algorithm requires a working space equal to the
- * size of the original array. The {@link
- * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
- * used to execute any parallel tasks.
- *
- * @param a the array to be sorted
- * @param fromIndex the index of the first element, inclusive, to be sorted
- * @param toIndex the index of the last element, exclusive, to be sorted
- *
- * @throws IllegalArgumentException if {@code fromIndex > toIndex}
- * @throws ArrayIndexOutOfBoundsException
- * if {@code fromIndex < 0} or {@code toIndex > a.length}
- *
- * @since 1.8
- */
- public static void parallelSort(char[] a, int fromIndex, int toIndex) {
- rangeCheck(a.length, fromIndex, toIndex);
- int nelements = toIndex - fromIndex;
- int gran = getSplitThreshold(nelements);
- FJChar.Sorter task = new FJChar.Sorter(a, new char[a.length], fromIndex,
- nelements, gran);
- task.invoke();
- }
-
- /**
- * Sorts the specified array into ascending numerical order.
- *
- * <p>Implementation note: The sorting algorithm is a parallel sort-merge
- * that breaks the array into sub-arrays that are themselves sorted and then
- * merged. When the sub-array length reaches a minimum granularity, the
- * sub-array is sorted using the appropriate {@link Arrays#sort(short[])
- * Arrays.sort} method. The algorithm requires a working space equal to the
- * size of the original array. The {@link
- * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
- * used to execute any parallel tasks.
- *
- * @param a the array to be sorted
- *
- * @since 1.8
- */
- public static void parallelSort(short[] a) {
- parallelSort(a, 0, a.length);
- }
-
- /**
- * Sorts the specified range of the array into ascending order. The range
- * to be sorted extends from the index {@code fromIndex}, inclusive, to
- * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
- * the range to be sorted is empty.
- *
- * <p>Implementation note: The sorting algorithm is a parallel sort-merge
- * that breaks the array into sub-arrays that are themselves sorted and then
- * merged. When the sub-array length reaches a minimum granularity, the
- * sub-array is sorted using the appropriate {@link Arrays#sort(short[])
- * Arrays.sort} method. The algorithm requires a working space equal to the
- * size of the original array. The {@link
- * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
- * used to execute any parallel tasks.
- *
- * @param a the array to be sorted
- * @param fromIndex the index of the first element, inclusive, to be sorted
- * @param toIndex the index of the last element, exclusive, to be sorted
- *
- * @throws IllegalArgumentException if {@code fromIndex > toIndex}
- * @throws ArrayIndexOutOfBoundsException
- * if {@code fromIndex < 0} or {@code toIndex > a.length}
- *
- * @since 1.8
- */
- public static void parallelSort(short[] a, int fromIndex, int toIndex) {
- rangeCheck(a.length, fromIndex, toIndex);
- int nelements = toIndex - fromIndex;
- int gran = getSplitThreshold(nelements);
- FJShort.Sorter task = new FJShort.Sorter(a, new short[a.length], fromIndex,
- nelements, gran);
- task.invoke();
- }
-
- /**
- * Sorts the specified array into ascending numerical order.
- *
- * <p>Implementation note: The sorting algorithm is a parallel sort-merge
- * that breaks the array into sub-arrays that are themselves sorted and then
- * merged. When the sub-array length reaches a minimum granularity, the
- * sub-array is sorted using the appropriate {@link Arrays#sort(int[])
- * Arrays.sort} method. The algorithm requires a working space equal to the
- * size of the original array. The {@link
- * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
- * used to execute any parallel tasks.
- *
- * @param a the array to be sorted
- *
- * @since 1.8
- */
- public static void parallelSort(int[] a) {
- parallelSort(a, 0, a.length);
- }
-
- /**
- * Sorts the specified range of the array into ascending order. The range
- * to be sorted extends from the index {@code fromIndex}, inclusive, to
- * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
- * the range to be sorted is empty.
- *
- * <p>Implementation note: The sorting algorithm is a parallel sort-merge
- * that breaks the array into sub-arrays that are themselves sorted and then
- * merged. When the sub-array length reaches a minimum granularity, the
- * sub-array is sorted using the appropriate {@link Arrays#sort(int[])
- * Arrays.sort} method. The algorithm requires a working space equal to the
- * size of the original array. The {@link
- * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
- * used to execute any parallel tasks.
- *
- * @param a the array to be sorted
- * @param fromIndex the index of the first element, inclusive, to be sorted
- * @param toIndex the index of the last element, exclusive, to be sorted
- *
- * @throws IllegalArgumentException if {@code fromIndex > toIndex}
- * @throws ArrayIndexOutOfBoundsException
- * if {@code fromIndex < 0} or {@code toIndex > a.length}
- *
- * @since 1.8
- */
- public static void parallelSort(int[] a, int fromIndex, int toIndex) {
- rangeCheck(a.length, fromIndex, toIndex);
- int nelements = toIndex - fromIndex;
- int gran = getSplitThreshold(nelements);
- FJInt.Sorter task = new FJInt.Sorter(a, new int[a.length], fromIndex,
- nelements, gran);
- task.invoke();
- }
-
- /**
- * Sorts the specified array into ascending numerical order.
- *
- * <p>Implementation note: The sorting algorithm is a parallel sort-merge
- * that breaks the array into sub-arrays that are themselves sorted and then
- * merged. When the sub-array length reaches a minimum granularity, the
- * sub-array is sorted using the appropriate {@link Arrays#sort(long[])
- * Arrays.sort} method. The algorithm requires a working space equal to the
- * size of the original array. The {@link
- * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
- * used to execute any parallel tasks.
- *
- * @param a the array to be sorted
- *
- * @since 1.8
- */
- public static void parallelSort(long[] a) {
- parallelSort(a, 0, a.length);
- }
-
- /**
- * Sorts the specified range of the array into ascending order. The range
- * to be sorted extends from the index {@code fromIndex}, inclusive, to
- * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
- * the range to be sorted is empty.
- *
- * <p>Implementation note: The sorting algorithm is a parallel sort-merge
- * that breaks the array into sub-arrays that are themselves sorted and then
- * merged. When the sub-array length reaches a minimum granularity, the
- * sub-array is sorted using the appropriate {@link Arrays#sort(long[])
- * Arrays.sort} method. The algorithm requires a working space equal to the
- * size of the original array. The {@link
- * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
- * used to execute any parallel tasks.
- *
- * @param a the array to be sorted
- * @param fromIndex the index of the first element, inclusive, to be sorted
- * @param toIndex the index of the last element, exclusive, to be sorted
- *
- * @throws IllegalArgumentException if {@code fromIndex > toIndex}
- * @throws ArrayIndexOutOfBoundsException
- * if {@code fromIndex < 0} or {@code toIndex > a.length}
- *
- * @since 1.8
- */
- public static void parallelSort(long[] a, int fromIndex, int toIndex) {
- rangeCheck(a.length, fromIndex, toIndex);
- int nelements = toIndex - fromIndex;
- int gran = getSplitThreshold(nelements);
- FJLong.Sorter task = new FJLong.Sorter(a, new long[a.length], fromIndex,
- nelements, gran);
- task.invoke();
- }
-
- /**
- * Sorts the specified array into ascending numerical order.
- *
- * <p>The {@code <} relation does not provide a total order on all float
- * values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
- * value compares neither less than, greater than, nor equal to any value,
- * even itself. This method uses the total order imposed by the method
- * {@link Float#compareTo}: {@code -0.0f} is treated as less than value
- * {@code 0.0f} and {@code Float.NaN} is considered greater than any
- * other value and all {@code Float.NaN} values are considered equal.
- *
- * <p>Implementation note: The sorting algorithm is a parallel sort-merge
- * that breaks the array into sub-arrays that are themselves sorted and then
- * merged. When the sub-array length reaches a minimum granularity, the
- * sub-array is sorted using the appropriate {@link Arrays#sort(float[])
- * Arrays.sort} method. The algorithm requires a working space equal to the
- * size of the original array. The {@link
- * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
- * used to execute any parallel tasks.
- *
- * @param a the array to be sorted
- *
- * @since 1.8
- */
- public static void parallelSort(float[] a) {
- parallelSort(a, 0, a.length);
- }
-
- /**
- * Sorts the specified range of the array into ascending order. The range
- * to be sorted extends from the index {@code fromIndex}, inclusive, to
- * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
- * the range to be sorted is empty.
- *
- * <p>The {@code <} relation does not provide a total order on all float
- * values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
- * value compares neither less than, greater than, nor equal to any value,
- * even itself. This method uses the total order imposed by the method
- * {@link Float#compareTo}: {@code -0.0f} is treated as less than value
- * {@code 0.0f} and {@code Float.NaN} is considered greater than any
- * other value and all {@code Float.NaN} values are considered equal.
- *
- * <p>Implementation note: The sorting algorithm is a parallel sort-merge
- * that breaks the array into sub-arrays that are themselves sorted and then
- * merged. When the sub-array length reaches a minimum granularity, the
- * sub-array is sorted using the appropriate {@link Arrays#sort(float[])
- * Arrays.sort} method. The algorithm requires a working space equal to the
- * size of the original array. The {@link
- * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
- * used to execute any parallel tasks.
- *
- * @param a the array to be sorted
- * @param fromIndex the index of the first element, inclusive, to be sorted
- * @param toIndex the index of the last element, exclusive, to be sorted
- *
- * @throws IllegalArgumentException if {@code fromIndex > toIndex}
- * @throws ArrayIndexOutOfBoundsException
- * if {@code fromIndex < 0} or {@code toIndex > a.length}
- *
- * @since 1.8
- */
- public static void parallelSort(float[] a, int fromIndex, int toIndex) {
- rangeCheck(a.length, fromIndex, toIndex);
- int nelements = toIndex - fromIndex;
- int gran = getSplitThreshold(nelements);
- FJFloat.Sorter task = new FJFloat.Sorter(a, new float[a.length], fromIndex,
- nelements, gran);
- task.invoke();
- }
-
- /**
- * Sorts the specified array into ascending numerical order.
- *
- * <p>The {@code <} relation does not provide a total order on all double
- * values: {@code -0.0d == 0.0d} is {@code true} and a {@code Double.NaN}
- * value compares neither less than, greater than, nor equal to any value,
- * even itself. This method uses the total order imposed by the method
- * {@link Double#compareTo}: {@code -0.0d} is treated as less than value
- * {@code 0.0d} and {@code Double.NaN} is considered greater than any
- * other value and all {@code Double.NaN} values are considered equal.
- *
- * <p>Implementation note: The sorting algorithm is a parallel sort-merge
- * that breaks the array into sub-arrays that are themselves sorted and then
- * merged. When the sub-array length reaches a minimum granularity, the
- * sub-array is sorted using the appropriate {@link Arrays#sort(double[])
- * Arrays.sort} method. The algorithm requires a working space equal to the
- * size of the original array. The {@link
- * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
- * used to execute any parallel tasks.
- *
- * @param a the array to be sorted
- *
- * @since 1.8
- */
- public static void parallelSort(double[] a) {
- parallelSort(a, 0, a.length);
- }
-
- /**
- * Sorts the specified range of the array into ascending order. The range
- * to be sorted extends from the index {@code fromIndex}, inclusive, to
- * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
- * the range to be sorted is empty.
- *
- * <p>The {@code <} relation does not provide a total order on all double
- * values: {@code -0.0d == 0.0d} is {@code true} and a {@code Double.NaN}
- * value compares neither less than, greater than, nor equal to any value,
- * even itself. This method uses the total order imposed by the method
- * {@link Double#compareTo}: {@code -0.0d} is treated as less than value
- * {@code 0.0d} and {@code Double.NaN} is considered greater than any
- * other value and all {@code Double.NaN} values are considered equal.
- *
- * <p>Implementation note: The sorting algorithm is a parallel sort-merge
- * that breaks the array into sub-arrays that are themselves sorted and then
- * merged. When the sub-array length reaches a minimum granularity, the
- * sub-array is sorted using the appropriate {@link Arrays#sort(double[])
- * Arrays.sort} method. The algorithm requires a working space equal to the
- * size of the original array. The {@link
- * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
- * used to execute any parallel tasks.
- *
- * @param a the array to be sorted
- * @param fromIndex the index of the first element, inclusive, to be sorted
- * @param toIndex the index of the last element, exclusive, to be sorted
- *
- * @throws IllegalArgumentException if {@code fromIndex > toIndex}
- * @throws ArrayIndexOutOfBoundsException
- * if {@code fromIndex < 0} or {@code toIndex > a.length}
- *
- * @since 1.8
- */
- public static void parallelSort(double[] a, int fromIndex, int toIndex) {
- rangeCheck(a.length, fromIndex, toIndex);
- int nelements = toIndex - fromIndex;
- int gran = getSplitThreshold(nelements);
- FJDouble.Sorter task = new FJDouble.Sorter(a, new double[a.length],
- fromIndex, nelements, gran);
- task.invoke();
- }
-
- /*
- * Parallel sorting of complex type arrays.
- */
-
- /**
- * Sorts the specified array of objects into ascending order, according
- * to the {@linkplain Comparable natural ordering} of its elements.
- * All elements in the array must implement the {@link Comparable}
- * interface. Furthermore, all elements in the array must be
- * <i>mutually comparable</i> (that is, {@code e1.compareTo(e2)} must
- * not throw a {@code ClassCastException} for any elements {@code e1}
- * and {@code e2} in the array).
- *
- * <p>This sort is not guaranteed to be <i>stable</i>: equal elements
- * may be reordered as a result of the sort.
- *
- * <p>Implementation note: The sorting algorithm is a parallel sort-merge
- * that breaks the array into sub-arrays that are themselves sorted and then
- * merged. When the sub-array length reaches a minimum granularity, the
- * sub-array is sorted using the appropriate {@link Arrays#sort(Object[])
- * Arrays.sort} method. The algorithm requires a working space equal to the
- * size of the original array. The {@link
- * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
- * used to execute any parallel tasks.
- *
- * @param a the array to be sorted
- *
- * @throws ClassCastException if the array contains elements that are not
- * <i>mutually comparable</i> (for example, strings and integers)
- * @throws IllegalArgumentException (optional) if the natural
- * ordering of the array elements is found to violate the
- * {@link Comparable} contract
- *
- * @since 1.8
- */
- public static <T extends Comparable<? super T>> void parallelSort(T[] a) {
- parallelSort(a, 0, a.length);
- }
-
- /**
- * Sorts the specified range of the specified array of objects into
- * ascending order, according to the
- * {@linkplain Comparable natural ordering} of its
- * elements. The range to be sorted extends from index
- * {@code fromIndex}, inclusive, to index {@code toIndex}, exclusive.
- * (If {@code fromIndex==toIndex}, the range to be sorted is empty.) All
- * elements in this range must implement the {@link Comparable}
- * interface. Furthermore, all elements in this range must be <i>mutually
- * comparable</i> (that is, {@code e1.compareTo(e2)} must not throw a
- * {@code ClassCastException} for any elements {@code e1} and
- * {@code e2} in the array).
- *
- * <p>This sort is not guaranteed to be <i>stable</i>: equal elements
- * may be reordered as a result of the sort.
- *
- * <p>Implementation note: The sorting algorithm is a parallel sort-merge
- * that breaks the array into sub-arrays that are themselves sorted and then
- * merged. When the sub-array length reaches a minimum granularity, the
- * sub-array is sorted using the appropriate {@link Arrays#sort(Object[])
- * Arrays.sort} method. The algorithm requires a working space equal to the
- * size of the original array. The {@link
- * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
- * used to execute any parallel tasks.
- *
- * @param a the array to be sorted
- * @param fromIndex the index of the first element (inclusive) to be
- * sorted
- * @param toIndex the index of the last element (exclusive) to be sorted
- * @throws IllegalArgumentException if {@code fromIndex > toIndex} or
- * (optional) if the natural ordering of the array elements is
- * found to violate the {@link Comparable} contract
- * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or
- * {@code toIndex > a.length}
- * @throws ClassCastException if the array contains elements that are
- * not <i>mutually comparable</i> (for example, strings and
- * integers).
- *
- * @since 1.8
- */
- public static <T extends Comparable<? super T>>
- void parallelSort(T[] a, int fromIndex, int toIndex) {
- rangeCheck(a.length, fromIndex, toIndex);
- int nelements = toIndex - fromIndex;
- Class<?> tc = a.getClass().getComponentType();
- @SuppressWarnings("unchecked")
- T[] workspace = (T[])Array.newInstance(tc, a.length);
- int gran = getSplitThreshold(nelements);
- FJComparable.Sorter<T> task = new FJComparable.Sorter<>(a, workspace,
- fromIndex,
- nelements, gran);
- task.invoke();
- }
-
- /**
- * Sorts the specified array of objects according to the order induced by
- * the specified comparator. All elements in the array must be
- * <i>mutually comparable</i> by the specified comparator (that is,
- * {@code c.compare(e1, e2)} must not throw a {@code ClassCastException}
- * for any elements {@code e1} and {@code e2} in the array).
- *
- * <p>This sort is not guaranteed to be <i>stable</i>: equal elements
- * may be reordered as a result of the sort.
- *
- * <p>Implementation note: The sorting algorithm is a parallel sort-merge
- * that breaks the array into sub-arrays that are themselves sorted and then
- * merged. When the sub-array length reaches a minimum granularity, the
- * sub-array is sorted using the appropriate {@link Arrays#sort(Object[])
- * Arrays.sort} method. The algorithm requires a working space equal to the
- * size of the original array. The {@link
- * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
- * used to execute any parallel tasks.
- *
- * @param a the array to be sorted
- * @param c the comparator to determine the order of the array. A
- * {@code null} value indicates that the elements'
- * {@linkplain Comparable natural ordering} should be used.
- * @throws ClassCastException if the array contains elements that are
- * not <i>mutually comparable</i> using the specified comparator
- * @throws IllegalArgumentException (optional) if the comparator is
- * found to violate the {@link java.util.Comparator} contract
- *
- * @since 1.8
- */
- public static <T> void parallelSort(T[] a, Comparator<? super T> c) {
- parallelSort(a, 0, a.length, c);
- }
-
- /**
- * Sorts the specified range of the specified array of objects according
- * to the order induced by the specified comparator. The range to be
- * sorted extends from index {@code fromIndex}, inclusive, to index
- * {@code toIndex}, exclusive. (If {@code fromIndex==toIndex}, the
- * range to be sorted is empty.) All elements in the range must be
- * <i>mutually comparable</i> by the specified comparator (that is,
- * {@code c.compare(e1, e2)} must not throw a {@code ClassCastException}
- * for any elements {@code e1} and {@code e2} in the range).
- *
- * <p>This sort is not guaranteed to be <i>stable</i>: equal elements
- * may be reordered as a result of the sort.
- *
- * <p>Implementation note: The sorting algorithm is a parallel sort-merge
- * that breaks the array into sub-arrays that are themselves sorted and then
- * merged. When the sub-array length reaches a minimum granularity, the
- * sub-array is sorted using the appropriate {@link Arrays#sort(Object[])
- * Arrays.sort} method. The algorithm requires a working space equal to the
- * size of the original array. The {@link
- * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
- * used to execute any parallel tasks.
- *
- * @param a the array to be sorted
- * @param fromIndex the index of the first element (inclusive) to be
- * sorted
- * @param toIndex the index of the last element (exclusive) to be sorted
- * @param c the comparator to determine the order of the array. A
- * {@code null} value indicates that the elements'
- * {@linkplain Comparable natural ordering} should be used.
- * @throws IllegalArgumentException if {@code fromIndex > toIndex} or
- * (optional) if the natural ordering of the array elements is
- * found to violate the {@link Comparable} contract
- * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or
- * {@code toIndex > a.length}
- * @throws ClassCastException if the array contains elements that are
- * not <i>mutually comparable</i> (for example, strings and
- * integers).
- *
- * @since 1.8
- */
- public static <T> void parallelSort(T[] a, int fromIndex, int toIndex,
- Comparator<? super T> c) {
- rangeCheck(a.length, fromIndex, toIndex);
- int nelements = toIndex - fromIndex;
- Class<?> tc = a.getClass().getComponentType();
- @SuppressWarnings("unchecked")
- T[] workspace = (T[])Array.newInstance(tc, a.length);
- int gran = getSplitThreshold(nelements);
- FJComparator.Sorter<T> task = new FJComparator.Sorter<>(a, workspace,
- fromIndex,
- nelements, gran, c);
- task.invoke();
- }
-
- /**
- * Returns the size threshold for splitting into subtasks.
- * By default, uses about 8 times as many tasks as threads
- *
- * @param n number of elements in the array to be processed
- */
- private static int getSplitThreshold(int n) {
- int p = java.util.concurrent.ForkJoinPool.getCommonPoolParallelism();
- int t = (p > 1) ? (1 + n / (p << 3)) : n;
- return t < MIN_ARRAY_SORT_GRAN ? MIN_ARRAY_SORT_GRAN : t;
- }
-
- /**
- * Checks that {@code fromIndex} and {@code toIndex} are in
- * the range and throws an appropriate exception, if they aren't.
- */
- private static void rangeCheck(int length, int fromIndex, int toIndex) {
- if (fromIndex > toIndex) {
- throw new IllegalArgumentException(
- "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
- }
- if (fromIndex < 0) {
- throw new ArrayIndexOutOfBoundsException(fromIndex);
- }
- if (toIndex > length) {
- throw new ArrayIndexOutOfBoundsException(toIndex);
- }
- }
-
// Searching
/**
--- a/jdk/src/share/classes/java/util/ArraysParallelSortHelpers.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/ArraysParallelSortHelpers.java Mon Jun 03 23:23:20 2013 -0700
@@ -25,6 +25,7 @@
package java.util;
import java.util.concurrent.RecursiveAction;
+import java.util.concurrent.CountedCompleter;
/**
* Helper utilities for the parallel sort methods in Arrays.parallelSort.
@@ -44,1180 +45,966 @@
* c. merge them together
* 3. merge together the two halves.
*
- * One reason for splitting in quarters is that this guarantees
- * that the final sort is in the main array, not the workspace
- * array. (workspace and main swap roles on each subsort step.)
- * Leaf-level sorts use a Sequential quicksort, that in turn uses
- * insertion sort if under threshold. Otherwise it uses median of
- * three to pick pivot, and loops rather than recurses along left
- * path.
- *
+ * One reason for splitting in quarters is that this guarantees that
+ * the final sort is in the main array, not the workspace array.
+ * (workspace and main swap roles on each subsort step.) Leaf-level
+ * sorts use the associated sequential sort.
*
- * Merger classes perform merging for Sorter. If big enough, splits Left
- * partition in half; finds the greatest point in Right partition
- * less than the beginning of the second half of Left via binary
- * search; and then, in parallel, merges left half of Left with
- * elements of Right up to split point, and merges right half of
- * Left with elements of R past split point. At leaf, it just
- * sequentially merges. This is all messy to code; sadly we need
- * distinct versions for each type.
+ * Merger classes perform merging for Sorter. They are structured
+ * such that if the underlying sort is stable (as is true for
+ * TimSort), then so is the full sort. If big enough, they split the
+ * largest of the two partitions in half, find the greatest point in
+ * smaller partition less than the beginning of the second half of
+ * larger via binary search; and then merge in parallel the two
+ * partitions. In part to ensure tasks are triggered in
+ * stability-preserving order, the current CountedCompleter design
+ * requires some little tasks to serve as place holders for triggering
+ * completion tasks. These classes (EmptyCompleter and Relay) don't
+ * need to keep track of the arrays, and are never themselves forked,
+ * so don't hold any task state.
*
+ * The primitive class versions (FJByte... FJDouble) are
+ * identical to each other except for type declarations.
+ *
+ * The base sequential sorts rely on non-public versions of TimSort,
+ * ComparableTimSort, and DualPivotQuicksort sort methods that accept
+ * temp workspace array slices that we will have already allocated, so
+ * avoids redundant allocation. (Except for DualPivotQuicksort byte[]
+ * sort, that does not ever use a workspace array.)
*/
/*package*/ class ArraysParallelSortHelpers {
- // RFE: we should only need a working array as large as the subarray
- // to be sorted, but the logic assumes that indices in the two
- // arrays always line-up
+ /*
+ * Style note: The task classes have a lot of parameters, that are
+ * stored as task fields and copied to local variables and used in
+ * compute() methods, We pack these into as few lines as possible,
+ * and hoist consistency checks among them before main loops, to
+ * reduce distraction.
+ */
- /** byte support class */
- static final class FJByte {
- static final class Sorter extends RecursiveAction {
- static final long serialVersionUID = 749471161188027634L;
- final byte[] a; // array to be sorted.
- final byte[] w; // workspace for merge
- final int origin; // origin of the part of array we deal with
- final int n; // Number of elements in (sub)arrays.
- final int gran; // split control
+ /**
+ * A placeholder task for Sorters, used for the lowest
+ * quartile task, that does not need to maintain array state.
+ */
+ static final class EmptyCompleter extends CountedCompleter<Void> {
+ static final long serialVersionUID = 2446542900576103244L;
+ EmptyCompleter(CountedCompleter<?> p) { super(p); }
+ public final void compute() { }
+ }
- Sorter(byte[] a, byte[] w, int origin, int n, int gran) {
- this.a = a;
- this.w = w;
- this.origin = origin;
- this.n = n;
- this.gran = gran;
- }
+ /**
+ * A trigger for secondary merge of two merges
+ */
+ static final class Relay extends CountedCompleter<Void> {
+ static final long serialVersionUID = 2446542900576103244L;
+ final CountedCompleter<?> task;
+ Relay(CountedCompleter<?> task) {
+ super(null, 1);
+ this.task = task;
+ }
+ public final void compute() { }
+ public final void onCompletion(CountedCompleter<?> t) {
+ task.compute();
+ }
+ }
- public void compute() {
- final int l = origin;
- final int g = gran;
- final int n = this.n;
- final byte[] a = this.a;
- final byte[] w = this.w;
- if (n > g) {
- int h = n >>> 1; // half
- int q = n >>> 2; // lower quarter index
- int u = h + q; // upper quarter
- FJSubSorter ls = new FJSubSorter(new Sorter(a, w, l, q, g),
- new Sorter(a, w, l+q, h-q, g),
- new Merger(a, w, l, q,
- l+q, h-q, l, g, null));
- FJSubSorter rs = new FJSubSorter(new Sorter(a, w, l+h, q, g),
- new Sorter(a, w, l+u, n-u, g),
- new Merger(a, w, l+h, q,
- l+u, n-u, l+h, g, null));
- rs.fork();
- ls.compute();
- if (rs.tryUnfork()) rs.compute(); else rs.join();
- new Merger(w, a, l, h,
- l+h, n-h, l, g, null).compute();
- } else {
- DualPivotQuicksort.sort(a, l, l+n-1); //skip rangeCheck
+ /** Object + Comparator support class */
+ static final class FJObject {
+ static final class Sorter<T> extends CountedCompleter<Void> {
+ static final long serialVersionUID = 2446542900576103244L;
+ final T[] a, w;
+ final int base, size, wbase, gran;
+ Comparator<? super T> comparator;
+ Sorter(CountedCompleter<?> par, T[] a, T[] w, int base, int size,
+ int wbase, int gran,
+ Comparator<? super T> comparator) {
+ super(par);
+ this.a = a; this.w = w; this.base = base; this.size = size;
+ this.wbase = wbase; this.gran = gran;
+ this.comparator = comparator;
+ }
+ public final void compute() {
+ CountedCompleter<?> s = this;
+ Comparator<? super T> c = this.comparator;
+ T[] a = this.a, w = this.w; // localize all params
+ int b = this.base, n = this.size, wb = this.wbase, g = this.gran;
+ while (n > g) {
+ int h = n >>> 1, q = h >>> 1, u = h + q; // quartiles
+ Relay fc = new Relay(new Merger<T>(s, w, a, wb, h,
+ wb+h, n-h, b, g, c));
+ Relay rc = new Relay(new Merger<T>(fc, a, w, b+h, q,
+ b+u, n-u, wb+h, g, c));
+ new Sorter<T>(rc, a, w, b+u, n-u, wb+u, g, c).fork();
+ new Sorter<T>(rc, a, w, b+h, q, wb+h, g, c).fork();;
+ Relay bc = new Relay(new Merger<T>(fc, a, w, b, q,
+ b+q, h-q, wb, g, c));
+ new Sorter<T>(bc, a, w, b+q, h-q, wb+q, g, c).fork();
+ s = new EmptyCompleter(bc);
+ n = q;
}
+ TimSort.sort(a, b, b + n, c, w, wb, n);
+ s.tryComplete();
}
}
- static final class Merger extends RecursiveAction {
- static final long serialVersionUID = -9090258248781844470L;
- final byte[] a;
- final byte[] w;
- final int lo;
- final int ln;
- final int ro;
- final int rn;
- final int wo;
- final int gran;
- final Merger next;
+ static final class Merger<T> extends CountedCompleter<Void> {
+ static final long serialVersionUID = 2446542900576103244L;
+ final T[] a, w; // main and workspace arrays
+ final int lbase, lsize, rbase, rsize, wbase, gran;
+ Comparator<? super T> comparator;
+ Merger(CountedCompleter<?> par, T[] a, T[] w,
+ int lbase, int lsize, int rbase,
+ int rsize, int wbase, int gran,
+ Comparator<? super T> comparator) {
+ super(par);
+ this.a = a; this.w = w;
+ this.lbase = lbase; this.lsize = lsize;
+ this.rbase = rbase; this.rsize = rsize;
+ this.wbase = wbase; this.gran = gran;
+ this.comparator = comparator;
+ }
- Merger(byte[] a, byte[] w, int lo, int ln, int ro, int rn, int wo,
- int gran, Merger next) {
- this.a = a;
- this.w = w;
- this.lo = lo;
- this.ln = ln;
- this.ro = ro;
- this.rn = rn;
- this.wo = wo;
- this.gran = gran;
- this.next = next;
+ public final void compute() {
+ Comparator<? super T> c = this.comparator;
+ T[] a = this.a, w = this.w; // localize all params
+ int lb = this.lbase, ln = this.lsize, rb = this.rbase,
+ rn = this.rsize, k = this.wbase, g = this.gran;
+ if (a == null || w == null || lb < 0 || rb < 0 || k < 0 ||
+ c == null)
+ throw new IllegalStateException(); // hoist checks
+ for (int lh, rh;;) { // split larger, find point in smaller
+ if (ln >= rn) {
+ if (ln <= g)
+ break;
+ rh = rn;
+ T split = a[(lh = ln >>> 1) + lb];
+ for (int lo = 0; lo < rh; ) {
+ int rm = (lo + rh) >>> 1;
+ if (c.compare(split, a[rm + rb]) <= 0)
+ rh = rm;
+ else
+ lo = rm + 1;
+ }
+ }
+ else {
+ if (rn <= g)
+ break;
+ lh = ln;
+ T split = a[(rh = rn >>> 1) + rb];
+ for (int lo = 0; lo < lh; ) {
+ int lm = (lo + lh) >>> 1;
+ if (c.compare(split, a[lm + lb]) <= 0)
+ lh = lm;
+ else
+ lo = lm + 1;
+ }
+ }
+ Merger<T> m = new Merger<T>(this, a, w, lb + lh, ln - lh,
+ rb + rh, rn - rh,
+ k + lh + rh, g, c);
+ rn = rh;
+ ln = lh;
+ addToPendingCount(1);
+ m.fork();
+ }
+
+ int lf = lb + ln, rf = rb + rn; // index bounds
+ while (lb < lf && rb < rf) {
+ T t, al, ar;
+ if (c.compare((al = a[lb]), (ar = a[rb])) <= 0) {
+ lb++; t = al;
+ }
+ else {
+ rb++; t = ar;
+ }
+ w[k++] = t;
+ }
+ if (rb < rf)
+ System.arraycopy(a, rb, w, k, rf - rb);
+ else if (lb < lf)
+ System.arraycopy(a, lb, w, k, lf - lb);
+
+ tryComplete();
}
- public void compute() {
- final byte[] a = this.a;
- final byte[] w = this.w;
- Merger rights = null;
- int nleft = ln;
- int nright = rn;
- while (nleft > gran) {
- int lh = nleft >>> 1;
- int splitIndex = lo + lh;
- byte split = a[splitIndex];
- int rl = 0;
- int rh = nright;
- while (rl < rh) {
- int mid = (rl + rh) >>> 1;
- if (split <= a[ro + mid])
- rh = mid;
- else
- rl = mid + 1;
+ }
+ } // FJObject
+
+ /** byte support class */
+ static final class FJByte {
+ static final class Sorter extends CountedCompleter<Void> {
+ static final long serialVersionUID = 2446542900576103244L;
+ final byte[] a, w;
+ final int base, size, wbase, gran;
+ Sorter(CountedCompleter<?> par, byte[] a, byte[] w, int base,
+ int size, int wbase, int gran) {
+ super(par);
+ this.a = a; this.w = w; this.base = base; this.size = size;
+ this.wbase = wbase; this.gran = gran;
+ }
+ public final void compute() {
+ CountedCompleter<?> s = this;
+ byte[] a = this.a, w = this.w; // localize all params
+ int b = this.base, n = this.size, wb = this.wbase, g = this.gran;
+ while (n > g) {
+ int h = n >>> 1, q = h >>> 1, u = h + q; // quartiles
+ Relay fc = new Relay(new Merger(s, w, a, wb, h,
+ wb+h, n-h, b, g));
+ Relay rc = new Relay(new Merger(fc, a, w, b+h, q,
+ b+u, n-u, wb+h, g));
+ new Sorter(rc, a, w, b+u, n-u, wb+u, g).fork();
+ new Sorter(rc, a, w, b+h, q, wb+h, g).fork();;
+ Relay bc = new Relay(new Merger(fc, a, w, b, q,
+ b+q, h-q, wb, g));
+ new Sorter(bc, a, w, b+q, h-q, wb+q, g).fork();
+ s = new EmptyCompleter(bc);
+ n = q;
+ }
+ DualPivotQuicksort.sort(a, b, b + n - 1);
+ s.tryComplete();
+ }
+ }
+
+ static final class Merger extends CountedCompleter<Void> {
+ static final long serialVersionUID = 2446542900576103244L;
+ final byte[] a, w; // main and workspace arrays
+ final int lbase, lsize, rbase, rsize, wbase, gran;
+ Merger(CountedCompleter<?> par, byte[] a, byte[] w,
+ int lbase, int lsize, int rbase,
+ int rsize, int wbase, int gran) {
+ super(par);
+ this.a = a; this.w = w;
+ this.lbase = lbase; this.lsize = lsize;
+ this.rbase = rbase; this.rsize = rsize;
+ this.wbase = wbase; this.gran = gran;
+ }
+
+ public final void compute() {
+ byte[] a = this.a, w = this.w; // localize all params
+ int lb = this.lbase, ln = this.lsize, rb = this.rbase,
+ rn = this.rsize, k = this.wbase, g = this.gran;
+ if (a == null || w == null || lb < 0 || rb < 0 || k < 0)
+ throw new IllegalStateException(); // hoist checks
+ for (int lh, rh;;) { // split larger, find point in smaller
+ if (ln >= rn) {
+ if (ln <= g)
+ break;
+ rh = rn;
+ byte split = a[(lh = ln >>> 1) + lb];
+ for (int lo = 0; lo < rh; ) {
+ int rm = (lo + rh) >>> 1;
+ if (split <= a[rm + rb])
+ rh = rm;
+ else
+ lo = rm + 1;
+ }
}
- (rights = new Merger(a, w, splitIndex, nleft-lh, ro+rh,
- nright-rh, wo+lh+rh, gran, rights)).fork();
- nleft = lh;
- nright = rh;
+ else {
+ if (rn <= g)
+ break;
+ lh = ln;
+ byte split = a[(rh = rn >>> 1) + rb];
+ for (int lo = 0; lo < lh; ) {
+ int lm = (lo + lh) >>> 1;
+ if (split <= a[lm + lb])
+ lh = lm;
+ else
+ lo = lm + 1;
+ }
+ }
+ Merger m = new Merger(this, a, w, lb + lh, ln - lh,
+ rb + rh, rn - rh,
+ k + lh + rh, g);
+ rn = rh;
+ ln = lh;
+ addToPendingCount(1);
+ m.fork();
}
- int l = lo;
- int lFence = l + nleft;
- int r = ro;
- int rFence = r + nright;
- int k = wo;
- while (l < lFence && r < rFence) {
- byte al = a[l];
- byte ar = a[r];
- byte t;
- if (al <= ar) {++l; t=al;} else {++r; t = ar;}
+ int lf = lb + ln, rf = rb + rn; // index bounds
+ while (lb < lf && rb < rf) {
+ byte t, al, ar;
+ if ((al = a[lb]) <= (ar = a[rb])) {
+ lb++; t = al;
+ }
+ else {
+ rb++; t = ar;
+ }
w[k++] = t;
}
- while (l < lFence)
- w[k++] = a[l++];
- while (r < rFence)
- w[k++] = a[r++];
- while (rights != null) {
- if (rights.tryUnfork())
- rights.compute();
- else
- rights.join();
- rights = rights.next;
- }
+ if (rb < rf)
+ System.arraycopy(a, rb, w, k, rf - rb);
+ else if (lb < lf)
+ System.arraycopy(a, lb, w, k, lf - lb);
+ tryComplete();
}
}
} // FJByte
/** char support class */
static final class FJChar {
- static final class Sorter extends RecursiveAction {
- static final long serialVersionUID = 8723376019074596641L;
- final char[] a; // array to be sorted.
- final char[] w; // workspace for merge
- final int origin; // origin of the part of array we deal with
- final int n; // Number of elements in (sub)arrays.
- final int gran; // split control
-
- Sorter(char[] a, char[] w, int origin, int n, int gran) {
- this.a = a;
- this.w = w;
- this.origin = origin;
- this.n = n;
- this.gran = gran;
+ static final class Sorter extends CountedCompleter<Void> {
+ static final long serialVersionUID = 2446542900576103244L;
+ final char[] a, w;
+ final int base, size, wbase, gran;
+ Sorter(CountedCompleter<?> par, char[] a, char[] w, int base,
+ int size, int wbase, int gran) {
+ super(par);
+ this.a = a; this.w = w; this.base = base; this.size = size;
+ this.wbase = wbase; this.gran = gran;
}
-
- public void compute() {
- final int l = origin;
- final int g = gran;
- final int n = this.n;
- final char[] a = this.a;
- final char[] w = this.w;
- if (n > g) {
- int h = n >>> 1; // half
- int q = n >>> 2; // lower quarter index
- int u = h + q; // upper quarter
- FJSubSorter ls = new FJSubSorter(new Sorter(a, w, l, q, g),
- new Sorter(a, w, l+q, h-q, g),
- new Merger(a, w, l, q,
- l+q, h-q, l, g, null));
- FJSubSorter rs = new FJSubSorter(new Sorter(a, w, l + h, q, g),
- new Sorter(a, w, l+u, n-u, g),
- new Merger(a, w, l+h, q,
- l+u, n-u, l+h, g, null));
- rs.fork();
- ls.compute();
- if (rs.tryUnfork()) rs.compute(); else rs.join();
- new Merger(w, a, l, h, l + h, n - h, l, g, null).compute();
- } else {
- DualPivotQuicksort.sort(a, l, l+n-1); // skip rangeCheck
+ public final void compute() {
+ CountedCompleter<?> s = this;
+ char[] a = this.a, w = this.w; // localize all params
+ int b = this.base, n = this.size, wb = this.wbase, g = this.gran;
+ while (n > g) {
+ int h = n >>> 1, q = h >>> 1, u = h + q; // quartiles
+ Relay fc = new Relay(new Merger(s, w, a, wb, h,
+ wb+h, n-h, b, g));
+ Relay rc = new Relay(new Merger(fc, a, w, b+h, q,
+ b+u, n-u, wb+h, g));
+ new Sorter(rc, a, w, b+u, n-u, wb+u, g).fork();
+ new Sorter(rc, a, w, b+h, q, wb+h, g).fork();;
+ Relay bc = new Relay(new Merger(fc, a, w, b, q,
+ b+q, h-q, wb, g));
+ new Sorter(bc, a, w, b+q, h-q, wb+q, g).fork();
+ s = new EmptyCompleter(bc);
+ n = q;
}
+ DualPivotQuicksort.sort(a, b, b + n - 1, w, wb, n);
+ s.tryComplete();
}
}
- static final class Merger extends RecursiveAction {
- static final long serialVersionUID = -1383975444621698926L;
- final char[] a;
- final char[] w;
- final int lo;
- final int ln;
- final int ro;
- final int rn;
- final int wo;
- final int gran;
- final Merger next;
-
- Merger(char[] a, char[] w, int lo, int ln, int ro, int rn, int wo,
- int gran, Merger next) {
- this.a = a;
- this.w = w;
- this.lo = lo;
- this.ln = ln;
- this.ro = ro;
- this.rn = rn;
- this.wo = wo;
- this.gran = gran;
- this.next = next;
+ static final class Merger extends CountedCompleter<Void> {
+ static final long serialVersionUID = 2446542900576103244L;
+ final char[] a, w; // main and workspace arrays
+ final int lbase, lsize, rbase, rsize, wbase, gran;
+ Merger(CountedCompleter<?> par, char[] a, char[] w,
+ int lbase, int lsize, int rbase,
+ int rsize, int wbase, int gran) {
+ super(par);
+ this.a = a; this.w = w;
+ this.lbase = lbase; this.lsize = lsize;
+ this.rbase = rbase; this.rsize = rsize;
+ this.wbase = wbase; this.gran = gran;
}
- public void compute() {
- final char[] a = this.a;
- final char[] w = this.w;
- Merger rights = null;
- int nleft = ln;
- int nright = rn;
- while (nleft > gran) {
- int lh = nleft >>> 1;
- int splitIndex = lo + lh;
- char split = a[splitIndex];
- int rl = 0;
- int rh = nright;
- while (rl < rh) {
- int mid = (rl + rh) >>> 1;
- if (split <= a[ro + mid])
- rh = mid;
- else
- rl = mid + 1;
+ public final void compute() {
+ char[] a = this.a, w = this.w; // localize all params
+ int lb = this.lbase, ln = this.lsize, rb = this.rbase,
+ rn = this.rsize, k = this.wbase, g = this.gran;
+ if (a == null || w == null || lb < 0 || rb < 0 || k < 0)
+ throw new IllegalStateException(); // hoist checks
+ for (int lh, rh;;) { // split larger, find point in smaller
+ if (ln >= rn) {
+ if (ln <= g)
+ break;
+ rh = rn;
+ char split = a[(lh = ln >>> 1) + lb];
+ for (int lo = 0; lo < rh; ) {
+ int rm = (lo + rh) >>> 1;
+ if (split <= a[rm + rb])
+ rh = rm;
+ else
+ lo = rm + 1;
+ }
}
- (rights = new Merger(a, w, splitIndex, nleft-lh, ro+rh,
- nright-rh, wo+lh+rh, gran, rights)).fork();
- nleft = lh;
- nright = rh;
+ else {
+ if (rn <= g)
+ break;
+ lh = ln;
+ char split = a[(rh = rn >>> 1) + rb];
+ for (int lo = 0; lo < lh; ) {
+ int lm = (lo + lh) >>> 1;
+ if (split <= a[lm + lb])
+ lh = lm;
+ else
+ lo = lm + 1;
+ }
+ }
+ Merger m = new Merger(this, a, w, lb + lh, ln - lh,
+ rb + rh, rn - rh,
+ k + lh + rh, g);
+ rn = rh;
+ ln = lh;
+ addToPendingCount(1);
+ m.fork();
}
- int l = lo;
- int lFence = l + nleft;
- int r = ro;
- int rFence = r + nright;
- int k = wo;
- while (l < lFence && r < rFence) {
- char al = a[l];
- char ar = a[r];
- char t;
- if (al <= ar) {++l; t=al;} else {++r; t = ar;}
+ int lf = lb + ln, rf = rb + rn; // index bounds
+ while (lb < lf && rb < rf) {
+ char t, al, ar;
+ if ((al = a[lb]) <= (ar = a[rb])) {
+ lb++; t = al;
+ }
+ else {
+ rb++; t = ar;
+ }
w[k++] = t;
}
- while (l < lFence)
- w[k++] = a[l++];
- while (r < rFence)
- w[k++] = a[r++];
- while (rights != null) {
- if (rights.tryUnfork())
- rights.compute();
- else
- rights.join();
- rights = rights.next;
- }
+ if (rb < rf)
+ System.arraycopy(a, rb, w, k, rf - rb);
+ else if (lb < lf)
+ System.arraycopy(a, lb, w, k, lf - lb);
+ tryComplete();
}
}
} // FJChar
/** short support class */
static final class FJShort {
- static final class Sorter extends RecursiveAction {
- static final long serialVersionUID = -7886754793730583084L;
- final short[] a; // array to be sorted.
- final short[] w; // workspace for merge
- final int origin; // origin of the part of array we deal with
- final int n; // Number of elements in (sub)arrays.
- final int gran; // split control
-
- Sorter(short[] a, short[] w, int origin, int n, int gran) {
- this.a = a;
- this.w = w;
- this.origin = origin;
- this.n = n;
- this.gran = gran;
+ static final class Sorter extends CountedCompleter<Void> {
+ static final long serialVersionUID = 2446542900576103244L;
+ final short[] a, w;
+ final int base, size, wbase, gran;
+ Sorter(CountedCompleter<?> par, short[] a, short[] w, int base,
+ int size, int wbase, int gran) {
+ super(par);
+ this.a = a; this.w = w; this.base = base; this.size = size;
+ this.wbase = wbase; this.gran = gran;
}
-
- public void compute() {
- final int l = origin;
- final int g = gran;
- final int n = this.n;
- final short[] a = this.a;
- final short[] w = this.w;
- if (n > g) {
- int h = n >>> 1; // half
- int q = n >>> 2; // lower quarter index
- int u = h + q; // upper quarter
- FJSubSorter ls = new FJSubSorter(new Sorter(a, w, l, q, g),
- new Sorter(a, w, l+q, h-q, g),
- new Merger(a, w, l, q,
- l+q, h-q, l, g, null));
- FJSubSorter rs = new FJSubSorter(new Sorter(a, w, l + h, q, g),
- new Sorter(a, w, l+u, n-u, g),
- new Merger(a, w, l+h, q,
- l+u, n-u, l+h, g, null));
- rs.fork();
- ls.compute();
- if (rs.tryUnfork()) rs.compute(); else rs.join();
- new Merger(w, a, l, h, l + h, n - h, l, g, null).compute();
- } else {
- DualPivotQuicksort.sort(a, l, l+n-1); // skip rangeCheck
+ public final void compute() {
+ CountedCompleter<?> s = this;
+ short[] a = this.a, w = this.w; // localize all params
+ int b = this.base, n = this.size, wb = this.wbase, g = this.gran;
+ while (n > g) {
+ int h = n >>> 1, q = h >>> 1, u = h + q; // quartiles
+ Relay fc = new Relay(new Merger(s, w, a, wb, h,
+ wb+h, n-h, b, g));
+ Relay rc = new Relay(new Merger(fc, a, w, b+h, q,
+ b+u, n-u, wb+h, g));
+ new Sorter(rc, a, w, b+u, n-u, wb+u, g).fork();
+ new Sorter(rc, a, w, b+h, q, wb+h, g).fork();;
+ Relay bc = new Relay(new Merger(fc, a, w, b, q,
+ b+q, h-q, wb, g));
+ new Sorter(bc, a, w, b+q, h-q, wb+q, g).fork();
+ s = new EmptyCompleter(bc);
+ n = q;
}
+ DualPivotQuicksort.sort(a, b, b + n - 1, w, wb, n);
+ s.tryComplete();
}
}
- static final class Merger extends RecursiveAction {
- static final long serialVersionUID = 3895749408536700048L;
- final short[] a;
- final short[] w;
- final int lo;
- final int ln;
- final int ro;
- final int rn;
- final int wo;
- final int gran;
- final Merger next;
-
- Merger(short[] a, short[] w, int lo, int ln, int ro, int rn, int wo,
- int gran, Merger next) {
- this.a = a;
- this.w = w;
- this.lo = lo;
- this.ln = ln;
- this.ro = ro;
- this.rn = rn;
- this.wo = wo;
- this.gran = gran;
- this.next = next;
+ static final class Merger extends CountedCompleter<Void> {
+ static final long serialVersionUID = 2446542900576103244L;
+ final short[] a, w; // main and workspace arrays
+ final int lbase, lsize, rbase, rsize, wbase, gran;
+ Merger(CountedCompleter<?> par, short[] a, short[] w,
+ int lbase, int lsize, int rbase,
+ int rsize, int wbase, int gran) {
+ super(par);
+ this.a = a; this.w = w;
+ this.lbase = lbase; this.lsize = lsize;
+ this.rbase = rbase; this.rsize = rsize;
+ this.wbase = wbase; this.gran = gran;
}
- public void compute() {
- final short[] a = this.a;
- final short[] w = this.w;
- Merger rights = null;
- int nleft = ln;
- int nright = rn;
- while (nleft > gran) {
- int lh = nleft >>> 1;
- int splitIndex = lo + lh;
- short split = a[splitIndex];
- int rl = 0;
- int rh = nright;
- while (rl < rh) {
- int mid = (rl + rh) >>> 1;
- if (split <= a[ro + mid])
- rh = mid;
- else
- rl = mid + 1;
+ public final void compute() {
+ short[] a = this.a, w = this.w; // localize all params
+ int lb = this.lbase, ln = this.lsize, rb = this.rbase,
+ rn = this.rsize, k = this.wbase, g = this.gran;
+ if (a == null || w == null || lb < 0 || rb < 0 || k < 0)
+ throw new IllegalStateException(); // hoist checks
+ for (int lh, rh;;) { // split larger, find point in smaller
+ if (ln >= rn) {
+ if (ln <= g)
+ break;
+ rh = rn;
+ short split = a[(lh = ln >>> 1) + lb];
+ for (int lo = 0; lo < rh; ) {
+ int rm = (lo + rh) >>> 1;
+ if (split <= a[rm + rb])
+ rh = rm;
+ else
+ lo = rm + 1;
+ }
}
- (rights = new Merger(a, w, splitIndex, nleft-lh, ro+rh,
- nright-rh, wo+lh+rh, gran, rights)).fork();
- nleft = lh;
- nright = rh;
+ else {
+ if (rn <= g)
+ break;
+ lh = ln;
+ short split = a[(rh = rn >>> 1) + rb];
+ for (int lo = 0; lo < lh; ) {
+ int lm = (lo + lh) >>> 1;
+ if (split <= a[lm + lb])
+ lh = lm;
+ else
+ lo = lm + 1;
+ }
+ }
+ Merger m = new Merger(this, a, w, lb + lh, ln - lh,
+ rb + rh, rn - rh,
+ k + lh + rh, g);
+ rn = rh;
+ ln = lh;
+ addToPendingCount(1);
+ m.fork();
}
- int l = lo;
- int lFence = l + nleft;
- int r = ro;
- int rFence = r + nright;
- int k = wo;
- while (l < lFence && r < rFence) {
- short al = a[l];
- short ar = a[r];
- short t;
- if (al <= ar) {++l; t=al;} else {++r; t = ar;}
+ int lf = lb + ln, rf = rb + rn; // index bounds
+ while (lb < lf && rb < rf) {
+ short t, al, ar;
+ if ((al = a[lb]) <= (ar = a[rb])) {
+ lb++; t = al;
+ }
+ else {
+ rb++; t = ar;
+ }
w[k++] = t;
}
- while (l < lFence)
- w[k++] = a[l++];
- while (r < rFence)
- w[k++] = a[r++];
- while (rights != null) {
- if (rights.tryUnfork())
- rights.compute();
- else
- rights.join();
- rights = rights.next;
- }
+ if (rb < rf)
+ System.arraycopy(a, rb, w, k, rf - rb);
+ else if (lb < lf)
+ System.arraycopy(a, lb, w, k, lf - lb);
+ tryComplete();
}
}
} // FJShort
/** int support class */
static final class FJInt {
- static final class Sorter extends RecursiveAction {
- static final long serialVersionUID = 4263311808957292729L;
- final int[] a; // array to be sorted.
- final int[] w; // workspace for merge
- final int origin; // origin of the part of array we deal with
- final int n; // Number of elements in (sub)arrays.
- final int gran; // split control
-
- Sorter(int[] a, int[] w, int origin, int n, int gran) {
- this.a = a;
- this.w = w;
- this.origin = origin;
- this.n = n;
- this.gran = gran;
+ static final class Sorter extends CountedCompleter<Void> {
+ static final long serialVersionUID = 2446542900576103244L;
+ final int[] a, w;
+ final int base, size, wbase, gran;
+ Sorter(CountedCompleter<?> par, int[] a, int[] w, int base,
+ int size, int wbase, int gran) {
+ super(par);
+ this.a = a; this.w = w; this.base = base; this.size = size;
+ this.wbase = wbase; this.gran = gran;
}
-
- public void compute() {
- final int l = origin;
- final int g = gran;
- final int n = this.n;
- final int[] a = this.a;
- final int[] w = this.w;
- if (n > g) {
- int h = n >>> 1; // half
- int q = n >>> 2; // lower quarter index
- int u = h + q; // upper quarter
- FJSubSorter ls = new FJSubSorter(new Sorter(a, w, l, q, g),
- new Sorter(a, w, l+q, h-q, g),
- new Merger(a, w, l, q,
- l+q, h-q, l, g, null));
- FJSubSorter rs = new FJSubSorter(new Sorter(a, w, l + h, q, g),
- new Sorter(a, w, l+u, n-u, g),
- new Merger(a, w, l+h, q,
- l+u, n-u, l+h, g, null));
- rs.fork();
- ls.compute();
- if (rs.tryUnfork()) rs.compute(); else rs.join();
- new Merger(w, a, l, h, l + h, n - h, l, g, null).compute();
- } else {
- DualPivotQuicksort.sort(a, l, l+n-1); // skip rangeCheck
+ public final void compute() {
+ CountedCompleter<?> s = this;
+ int[] a = this.a, w = this.w; // localize all params
+ int b = this.base, n = this.size, wb = this.wbase, g = this.gran;
+ while (n > g) {
+ int h = n >>> 1, q = h >>> 1, u = h + q; // quartiles
+ Relay fc = new Relay(new Merger(s, w, a, wb, h,
+ wb+h, n-h, b, g));
+ Relay rc = new Relay(new Merger(fc, a, w, b+h, q,
+ b+u, n-u, wb+h, g));
+ new Sorter(rc, a, w, b+u, n-u, wb+u, g).fork();
+ new Sorter(rc, a, w, b+h, q, wb+h, g).fork();;
+ Relay bc = new Relay(new Merger(fc, a, w, b, q,
+ b+q, h-q, wb, g));
+ new Sorter(bc, a, w, b+q, h-q, wb+q, g).fork();
+ s = new EmptyCompleter(bc);
+ n = q;
}
+ DualPivotQuicksort.sort(a, b, b + n - 1, w, wb, n);
+ s.tryComplete();
}
}
- static final class Merger extends RecursiveAction {
- static final long serialVersionUID = -8727507284219982792L;
- final int[] a;
- final int[] w;
- final int lo;
- final int ln;
- final int ro;
- final int rn;
- final int wo;
- final int gran;
- final Merger next;
-
- Merger(int[] a, int[] w, int lo, int ln, int ro, int rn, int wo,
- int gran, Merger next) {
- this.a = a;
- this.w = w;
- this.lo = lo;
- this.ln = ln;
- this.ro = ro;
- this.rn = rn;
- this.wo = wo;
- this.gran = gran;
- this.next = next;
+ static final class Merger extends CountedCompleter<Void> {
+ static final long serialVersionUID = 2446542900576103244L;
+ final int[] a, w; // main and workspace arrays
+ final int lbase, lsize, rbase, rsize, wbase, gran;
+ Merger(CountedCompleter<?> par, int[] a, int[] w,
+ int lbase, int lsize, int rbase,
+ int rsize, int wbase, int gran) {
+ super(par);
+ this.a = a; this.w = w;
+ this.lbase = lbase; this.lsize = lsize;
+ this.rbase = rbase; this.rsize = rsize;
+ this.wbase = wbase; this.gran = gran;
}
- public void compute() {
- final int[] a = this.a;
- final int[] w = this.w;
- Merger rights = null;
- int nleft = ln;
- int nright = rn;
- while (nleft > gran) {
- int lh = nleft >>> 1;
- int splitIndex = lo + lh;
- int split = a[splitIndex];
- int rl = 0;
- int rh = nright;
- while (rl < rh) {
- int mid = (rl + rh) >>> 1;
- if (split <= a[ro + mid])
- rh = mid;
- else
- rl = mid + 1;
+ public final void compute() {
+ int[] a = this.a, w = this.w; // localize all params
+ int lb = this.lbase, ln = this.lsize, rb = this.rbase,
+ rn = this.rsize, k = this.wbase, g = this.gran;
+ if (a == null || w == null || lb < 0 || rb < 0 || k < 0)
+ throw new IllegalStateException(); // hoist checks
+ for (int lh, rh;;) { // split larger, find point in smaller
+ if (ln >= rn) {
+ if (ln <= g)
+ break;
+ rh = rn;
+ int split = a[(lh = ln >>> 1) + lb];
+ for (int lo = 0; lo < rh; ) {
+ int rm = (lo + rh) >>> 1;
+ if (split <= a[rm + rb])
+ rh = rm;
+ else
+ lo = rm + 1;
+ }
}
- (rights = new Merger(a, w, splitIndex, nleft-lh, ro+rh,
- nright-rh, wo+lh+rh, gran, rights)).fork();
- nleft = lh;
- nright = rh;
+ else {
+ if (rn <= g)
+ break;
+ lh = ln;
+ int split = a[(rh = rn >>> 1) + rb];
+ for (int lo = 0; lo < lh; ) {
+ int lm = (lo + lh) >>> 1;
+ if (split <= a[lm + lb])
+ lh = lm;
+ else
+ lo = lm + 1;
+ }
+ }
+ Merger m = new Merger(this, a, w, lb + lh, ln - lh,
+ rb + rh, rn - rh,
+ k + lh + rh, g);
+ rn = rh;
+ ln = lh;
+ addToPendingCount(1);
+ m.fork();
}
- int l = lo;
- int lFence = l + nleft;
- int r = ro;
- int rFence = r + nright;
- int k = wo;
- while (l < lFence && r < rFence) {
- int al = a[l];
- int ar = a[r];
- int t;
- if (al <= ar) {++l; t=al;} else {++r; t = ar;}
+ int lf = lb + ln, rf = rb + rn; // index bounds
+ while (lb < lf && rb < rf) {
+ int t, al, ar;
+ if ((al = a[lb]) <= (ar = a[rb])) {
+ lb++; t = al;
+ }
+ else {
+ rb++; t = ar;
+ }
w[k++] = t;
}
- while (l < lFence)
- w[k++] = a[l++];
- while (r < rFence)
- w[k++] = a[r++];
- while (rights != null) {
- if (rights.tryUnfork())
- rights.compute();
- else
- rights.join();
- rights = rights.next;
- }
+ if (rb < rf)
+ System.arraycopy(a, rb, w, k, rf - rb);
+ else if (lb < lf)
+ System.arraycopy(a, lb, w, k, lf - lb);
+ tryComplete();
}
}
} // FJInt
/** long support class */
static final class FJLong {
- static final class Sorter extends RecursiveAction {
- static final long serialVersionUID = 6553695007444392455L;
- final long[] a; // array to be sorted.
- final long[] w; // workspace for merge
- final int origin; // origin of the part of array we deal with
- final int n; // Number of elements in (sub)arrays.
- final int gran; // split control
-
- Sorter(long[] a, long[] w, int origin, int n, int gran) {
- this.a = a;
- this.w = w;
- this.origin = origin;
- this.n = n;
- this.gran = gran;
+ static final class Sorter extends CountedCompleter<Void> {
+ static final long serialVersionUID = 2446542900576103244L;
+ final long[] a, w;
+ final int base, size, wbase, gran;
+ Sorter(CountedCompleter<?> par, long[] a, long[] w, int base,
+ int size, int wbase, int gran) {
+ super(par);
+ this.a = a; this.w = w; this.base = base; this.size = size;
+ this.wbase = wbase; this.gran = gran;
}
-
- public void compute() {
- final int l = origin;
- final int g = gran;
- final int n = this.n;
- final long[] a = this.a;
- final long[] w = this.w;
- if (n > g) {
- int h = n >>> 1; // half
- int q = n >>> 2; // lower quarter index
- int u = h + q; // upper quarter
- FJSubSorter ls = new FJSubSorter(new Sorter(a, w, l, q, g),
- new Sorter(a, w, l+q, h-q, g),
- new Merger(a, w, l, q,
- l+q, h-q, l, g, null));
- FJSubSorter rs = new FJSubSorter(new Sorter(a, w, l + h, q, g),
- new Sorter(a, w, l+u, n-u, g),
- new Merger(a, w, l+h, q,
- l+u, n-u, l+h, g, null));
- rs.fork();
- ls.compute();
- if (rs.tryUnfork()) rs.compute(); else rs.join();
- new Merger(w, a, l, h, l + h, n - h, l, g, null).compute();
- } else {
- DualPivotQuicksort.sort(a, l, l+n-1); // skip rangeCheck
+ public final void compute() {
+ CountedCompleter<?> s = this;
+ long[] a = this.a, w = this.w; // localize all params
+ int b = this.base, n = this.size, wb = this.wbase, g = this.gran;
+ while (n > g) {
+ int h = n >>> 1, q = h >>> 1, u = h + q; // quartiles
+ Relay fc = new Relay(new Merger(s, w, a, wb, h,
+ wb+h, n-h, b, g));
+ Relay rc = new Relay(new Merger(fc, a, w, b+h, q,
+ b+u, n-u, wb+h, g));
+ new Sorter(rc, a, w, b+u, n-u, wb+u, g).fork();
+ new Sorter(rc, a, w, b+h, q, wb+h, g).fork();;
+ Relay bc = new Relay(new Merger(fc, a, w, b, q,
+ b+q, h-q, wb, g));
+ new Sorter(bc, a, w, b+q, h-q, wb+q, g).fork();
+ s = new EmptyCompleter(bc);
+ n = q;
}
+ DualPivotQuicksort.sort(a, b, b + n - 1, w, wb, n);
+ s.tryComplete();
}
}
- static final class Merger extends RecursiveAction {
- static final long serialVersionUID = 8843567516333283861L;
- final long[] a;
- final long[] w;
- final int lo;
- final int ln;
- final int ro;
- final int rn;
- final int wo;
- final int gran;
- final Merger next;
-
- Merger(long[] a, long[] w, int lo, int ln, int ro, int rn, int wo,
- int gran, Merger next) {
- this.a = a;
- this.w = w;
- this.lo = lo;
- this.ln = ln;
- this.ro = ro;
- this.rn = rn;
- this.wo = wo;
- this.gran = gran;
- this.next = next;
+ static final class Merger extends CountedCompleter<Void> {
+ static final long serialVersionUID = 2446542900576103244L;
+ final long[] a, w; // main and workspace arrays
+ final int lbase, lsize, rbase, rsize, wbase, gran;
+ Merger(CountedCompleter<?> par, long[] a, long[] w,
+ int lbase, int lsize, int rbase,
+ int rsize, int wbase, int gran) {
+ super(par);
+ this.a = a; this.w = w;
+ this.lbase = lbase; this.lsize = lsize;
+ this.rbase = rbase; this.rsize = rsize;
+ this.wbase = wbase; this.gran = gran;
}
- public void compute() {
- final long[] a = this.a;
- final long[] w = this.w;
- Merger rights = null;
- int nleft = ln;
- int nright = rn;
- while (nleft > gran) {
- int lh = nleft >>> 1;
- int splitIndex = lo + lh;
- long split = a[splitIndex];
- int rl = 0;
- int rh = nright;
- while (rl < rh) {
- int mid = (rl + rh) >>> 1;
- if (split <= a[ro + mid])
- rh = mid;
- else
- rl = mid + 1;
+ public final void compute() {
+ long[] a = this.a, w = this.w; // localize all params
+ int lb = this.lbase, ln = this.lsize, rb = this.rbase,
+ rn = this.rsize, k = this.wbase, g = this.gran;
+ if (a == null || w == null || lb < 0 || rb < 0 || k < 0)
+ throw new IllegalStateException(); // hoist checks
+ for (int lh, rh;;) { // split larger, find point in smaller
+ if (ln >= rn) {
+ if (ln <= g)
+ break;
+ rh = rn;
+ long split = a[(lh = ln >>> 1) + lb];
+ for (int lo = 0; lo < rh; ) {
+ int rm = (lo + rh) >>> 1;
+ if (split <= a[rm + rb])
+ rh = rm;
+ else
+ lo = rm + 1;
+ }
}
- (rights = new Merger(a, w, splitIndex, nleft-lh, ro+rh,
- nright-rh, wo+lh+rh, gran, rights)).fork();
- nleft = lh;
- nright = rh;
+ else {
+ if (rn <= g)
+ break;
+ lh = ln;
+ long split = a[(rh = rn >>> 1) + rb];
+ for (int lo = 0; lo < lh; ) {
+ int lm = (lo + lh) >>> 1;
+ if (split <= a[lm + lb])
+ lh = lm;
+ else
+ lo = lm + 1;
+ }
+ }
+ Merger m = new Merger(this, a, w, lb + lh, ln - lh,
+ rb + rh, rn - rh,
+ k + lh + rh, g);
+ rn = rh;
+ ln = lh;
+ addToPendingCount(1);
+ m.fork();
}
- int l = lo;
- int lFence = l + nleft;
- int r = ro;
- int rFence = r + nright;
- int k = wo;
- while (l < lFence && r < rFence) {
- long al = a[l];
- long ar = a[r];
- long t;
- if (al <= ar) {++l; t=al;} else {++r; t = ar;}
+ int lf = lb + ln, rf = rb + rn; // index bounds
+ while (lb < lf && rb < rf) {
+ long t, al, ar;
+ if ((al = a[lb]) <= (ar = a[rb])) {
+ lb++; t = al;
+ }
+ else {
+ rb++; t = ar;
+ }
w[k++] = t;
}
- while (l < lFence)
- w[k++] = a[l++];
- while (r < rFence)
- w[k++] = a[r++];
- while (rights != null) {
- if (rights.tryUnfork())
- rights.compute();
- else
- rights.join();
- rights = rights.next;
- }
+ if (rb < rf)
+ System.arraycopy(a, rb, w, k, rf - rb);
+ else if (lb < lf)
+ System.arraycopy(a, lb, w, k, lf - lb);
+ tryComplete();
}
}
} // FJLong
/** float support class */
static final class FJFloat {
- static final class Sorter extends RecursiveAction {
- static final long serialVersionUID = 1602600178202763377L;
- final float[] a; // array to be sorted.
- final float[] w; // workspace for merge
- final int origin; // origin of the part of array we deal with
- final int n; // Number of elements in (sub)arrays.
- final int gran; // split control
-
- Sorter(float[] a, float[] w, int origin, int n, int gran) {
- this.a = a;
- this.w = w;
- this.origin = origin;
- this.n = n;
- this.gran = gran;
+ static final class Sorter extends CountedCompleter<Void> {
+ static final long serialVersionUID = 2446542900576103244L;
+ final float[] a, w;
+ final int base, size, wbase, gran;
+ Sorter(CountedCompleter<?> par, float[] a, float[] w, int base,
+ int size, int wbase, int gran) {
+ super(par);
+ this.a = a; this.w = w; this.base = base; this.size = size;
+ this.wbase = wbase; this.gran = gran;
}
-
- public void compute() {
- final int l = origin;
- final int g = gran;
- final int n = this.n;
- final float[] a = this.a;
- final float[] w = this.w;
- if (n > g) {
- int h = n >>> 1; // half
- int q = n >>> 2; // lower quarter index
- int u = h + q; // upper quarter
- FJSubSorter ls = new FJSubSorter(new Sorter(a, w, l, q, g),
- new Sorter(a, w, l+q, h-q, g),
- new Merger(a, w, l, q,
- l+q, h-q, l, g, null));
- FJSubSorter rs = new FJSubSorter(new Sorter(a, w, l + h, q, g),
- new Sorter(a, w, l+u, n-u, g),
- new Merger(a, w, l+h, q,
- l+u, n-u, l+h, g, null));
- rs.fork();
- ls.compute();
- if (rs.tryUnfork()) rs.compute(); else rs.join();
- new Merger(w, a, l, h, l + h, n - h, l, g, null).compute();
- } else {
- DualPivotQuicksort.sort(a, l, l+n-1); // skip rangeCheck
+ public final void compute() {
+ CountedCompleter<?> s = this;
+ float[] a = this.a, w = this.w; // localize all params
+ int b = this.base, n = this.size, wb = this.wbase, g = this.gran;
+ while (n > g) {
+ int h = n >>> 1, q = h >>> 1, u = h + q; // quartiles
+ Relay fc = new Relay(new Merger(s, w, a, wb, h,
+ wb+h, n-h, b, g));
+ Relay rc = new Relay(new Merger(fc, a, w, b+h, q,
+ b+u, n-u, wb+h, g));
+ new Sorter(rc, a, w, b+u, n-u, wb+u, g).fork();
+ new Sorter(rc, a, w, b+h, q, wb+h, g).fork();;
+ Relay bc = new Relay(new Merger(fc, a, w, b, q,
+ b+q, h-q, wb, g));
+ new Sorter(bc, a, w, b+q, h-q, wb+q, g).fork();
+ s = new EmptyCompleter(bc);
+ n = q;
}
+ DualPivotQuicksort.sort(a, b, b + n - 1, w, wb, n);
+ s.tryComplete();
}
}
- static final class Merger extends RecursiveAction {
- static final long serialVersionUID = 1518176433845397426L;
- final float[] a;
- final float[] w;
- final int lo;
- final int ln;
- final int ro;
- final int rn;
- final int wo;
- final int gran;
- final Merger next;
-
- Merger(float[] a, float[] w, int lo, int ln, int ro, int rn, int wo,
- int gran, Merger next) {
- this.a = a;
- this.w = w;
- this.lo = lo;
- this.ln = ln;
- this.ro = ro;
- this.rn = rn;
- this.wo = wo;
- this.gran = gran;
- this.next = next;
+ static final class Merger extends CountedCompleter<Void> {
+ static final long serialVersionUID = 2446542900576103244L;
+ final float[] a, w; // main and workspace arrays
+ final int lbase, lsize, rbase, rsize, wbase, gran;
+ Merger(CountedCompleter<?> par, float[] a, float[] w,
+ int lbase, int lsize, int rbase,
+ int rsize, int wbase, int gran) {
+ super(par);
+ this.a = a; this.w = w;
+ this.lbase = lbase; this.lsize = lsize;
+ this.rbase = rbase; this.rsize = rsize;
+ this.wbase = wbase; this.gran = gran;
}
- public void compute() {
- final float[] a = this.a;
- final float[] w = this.w;
- Merger rights = null;
- int nleft = ln;
- int nright = rn;
- while (nleft > gran) {
- int lh = nleft >>> 1;
- int splitIndex = lo + lh;
- float split = a[splitIndex];
- int rl = 0;
- int rh = nright;
- while (rl < rh) {
- int mid = (rl + rh) >>> 1;
- if (Float.compare(split, a[ro+mid]) <= 0)
- rh = mid;
- else
- rl = mid + 1;
+ public final void compute() {
+ float[] a = this.a, w = this.w; // localize all params
+ int lb = this.lbase, ln = this.lsize, rb = this.rbase,
+ rn = this.rsize, k = this.wbase, g = this.gran;
+ if (a == null || w == null || lb < 0 || rb < 0 || k < 0)
+ throw new IllegalStateException(); // hoist checks
+ for (int lh, rh;;) { // split larger, find point in smaller
+ if (ln >= rn) {
+ if (ln <= g)
+ break;
+ rh = rn;
+ float split = a[(lh = ln >>> 1) + lb];
+ for (int lo = 0; lo < rh; ) {
+ int rm = (lo + rh) >>> 1;
+ if (split <= a[rm + rb])
+ rh = rm;
+ else
+ lo = rm + 1;
+ }
}
- (rights = new Merger(a, w, splitIndex, nleft-lh, ro+rh,
- nright-rh, wo+lh+rh, gran, rights)).fork();
- nleft = lh;
- nright = rh;
+ else {
+ if (rn <= g)
+ break;
+ lh = ln;
+ float split = a[(rh = rn >>> 1) + rb];
+ for (int lo = 0; lo < lh; ) {
+ int lm = (lo + lh) >>> 1;
+ if (split <= a[lm + lb])
+ lh = lm;
+ else
+ lo = lm + 1;
+ }
+ }
+ Merger m = new Merger(this, a, w, lb + lh, ln - lh,
+ rb + rh, rn - rh,
+ k + lh + rh, g);
+ rn = rh;
+ ln = lh;
+ addToPendingCount(1);
+ m.fork();
}
- int l = lo;
- int lFence = l + nleft;
- int r = ro;
- int rFence = r + nright;
- int k = wo;
- while (l < lFence && r < rFence) {
- float al = a[l];
- float ar = a[r];
- float t;
- if (Float.compare(al, ar) <= 0) {
- ++l;
- t = al;
- } else {
- ++r;
- t = ar;
+ int lf = lb + ln, rf = rb + rn; // index bounds
+ while (lb < lf && rb < rf) {
+ float t, al, ar;
+ if ((al = a[lb]) <= (ar = a[rb])) {
+ lb++; t = al;
+ }
+ else {
+ rb++; t = ar;
}
w[k++] = t;
}
- while (l < lFence)
- w[k++] = a[l++];
- while (r < rFence)
- w[k++] = a[r++];
- while (rights != null) {
- if (rights.tryUnfork())
- rights.compute();
- else
- rights.join();
- rights = rights.next;
- }
+ if (rb < rf)
+ System.arraycopy(a, rb, w, k, rf - rb);
+ else if (lb < lf)
+ System.arraycopy(a, lb, w, k, lf - lb);
+ tryComplete();
}
}
} // FJFloat
/** double support class */
static final class FJDouble {
- static final class Sorter extends RecursiveAction {
+ static final class Sorter extends CountedCompleter<Void> {
static final long serialVersionUID = 2446542900576103244L;
- final double[] a; // array to be sorted.
- final double[] w; // workspace for merge
- final int origin; // origin of the part of array we deal with
- final int n; // Number of elements in (sub)arrays.
- final int gran; // split control
-
- Sorter(double[] a, double[] w, int origin, int n, int gran) {
- this.a = a;
- this.w = w;
- this.origin = origin;
- this.n = n;
- this.gran = gran;
+ final double[] a, w;
+ final int base, size, wbase, gran;
+ Sorter(CountedCompleter<?> par, double[] a, double[] w, int base,
+ int size, int wbase, int gran) {
+ super(par);
+ this.a = a; this.w = w; this.base = base; this.size = size;
+ this.wbase = wbase; this.gran = gran;
}
-
- public void compute() {
- final int l = origin;
- final int g = gran;
- final int n = this.n;
- final double[] a = this.a;
- final double[] w = this.w;
- if (n > g) {
- int h = n >>> 1; // half
- int q = n >>> 2; // lower quarter index
- int u = h + q; // upper quarter
- FJSubSorter ls = new FJSubSorter(new Sorter(a, w, l, q, g),
- new Sorter(a, w, l+q, h-q, g),
- new Merger(a, w, l, q,
- l+q, h-q, l, g, null));
- FJSubSorter rs = new FJSubSorter(new Sorter(a, w, l + h, q, g),
- new Sorter(a, w, l+u, n-u, g),
- new Merger(a, w, l+h, q,
- l+u, n-u, l+h, g, null));
- rs.fork();
- ls.compute();
- if (rs.tryUnfork()) rs.compute(); else rs.join();
- new Merger(w, a, l, h, l + h, n - h, l, g, null).compute();
- } else {
- DualPivotQuicksort.sort(a, l, l+n-1); // skip rangeCheck
+ public final void compute() {
+ CountedCompleter<?> s = this;
+ double[] a = this.a, w = this.w; // localize all params
+ int b = this.base, n = this.size, wb = this.wbase, g = this.gran;
+ while (n > g) {
+ int h = n >>> 1, q = h >>> 1, u = h + q; // quartiles
+ Relay fc = new Relay(new Merger(s, w, a, wb, h,
+ wb+h, n-h, b, g));
+ Relay rc = new Relay(new Merger(fc, a, w, b+h, q,
+ b+u, n-u, wb+h, g));
+ new Sorter(rc, a, w, b+u, n-u, wb+u, g).fork();
+ new Sorter(rc, a, w, b+h, q, wb+h, g).fork();;
+ Relay bc = new Relay(new Merger(fc, a, w, b, q,
+ b+q, h-q, wb, g));
+ new Sorter(bc, a, w, b+q, h-q, wb+q, g).fork();
+ s = new EmptyCompleter(bc);
+ n = q;
}
+ DualPivotQuicksort.sort(a, b, b + n - 1, w, wb, n);
+ s.tryComplete();
}
}
- static final class Merger extends RecursiveAction {
- static final long serialVersionUID = 8076242187166127592L;
- final double[] a;
- final double[] w;
- final int lo;
- final int ln;
- final int ro;
- final int rn;
- final int wo;
- final int gran;
- final Merger next;
-
- Merger(double[] a, double[] w, int lo, int ln, int ro, int rn, int wo,
- int gran, Merger next) {
- this.a = a;
- this.w = w;
- this.lo = lo;
- this.ln = ln;
- this.ro = ro;
- this.rn = rn;
- this.wo = wo;
- this.gran = gran;
- this.next = next;
+ static final class Merger extends CountedCompleter<Void> {
+ static final long serialVersionUID = 2446542900576103244L;
+ final double[] a, w; // main and workspace arrays
+ final int lbase, lsize, rbase, rsize, wbase, gran;
+ Merger(CountedCompleter<?> par, double[] a, double[] w,
+ int lbase, int lsize, int rbase,
+ int rsize, int wbase, int gran) {
+ super(par);
+ this.a = a; this.w = w;
+ this.lbase = lbase; this.lsize = lsize;
+ this.rbase = rbase; this.rsize = rsize;
+ this.wbase = wbase; this.gran = gran;
}
- public void compute() {
- final double[] a = this.a;
- final double[] w = this.w;
- Merger rights = null;
- int nleft = ln;
- int nright = rn;
- while (nleft > gran) {
- int lh = nleft >>> 1;
- int splitIndex = lo + lh;
- double split = a[splitIndex];
- int rl = 0;
- int rh = nright;
- while (rl < rh) {
- int mid = (rl + rh) >>> 1;
- if (Double.compare(split, a[ro+mid]) <= 0)
- rh = mid;
- else
- rl = mid + 1;
+ public final void compute() {
+ double[] a = this.a, w = this.w; // localize all params
+ int lb = this.lbase, ln = this.lsize, rb = this.rbase,
+ rn = this.rsize, k = this.wbase, g = this.gran;
+ if (a == null || w == null || lb < 0 || rb < 0 || k < 0)
+ throw new IllegalStateException(); // hoist checks
+ for (int lh, rh;;) { // split larger, find point in smaller
+ if (ln >= rn) {
+ if (ln <= g)
+ break;
+ rh = rn;
+ double split = a[(lh = ln >>> 1) + lb];
+ for (int lo = 0; lo < rh; ) {
+ int rm = (lo + rh) >>> 1;
+ if (split <= a[rm + rb])
+ rh = rm;
+ else
+ lo = rm + 1;
+ }
}
- (rights = new Merger(a, w, splitIndex, nleft-lh, ro+rh,
- nright-rh, wo+lh+rh, gran, rights)).fork();
- nleft = lh;
- nright = rh;
+ else {
+ if (rn <= g)
+ break;
+ lh = ln;
+ double split = a[(rh = rn >>> 1) + rb];
+ for (int lo = 0; lo < lh; ) {
+ int lm = (lo + lh) >>> 1;
+ if (split <= a[lm + lb])
+ lh = lm;
+ else
+ lo = lm + 1;
+ }
+ }
+ Merger m = new Merger(this, a, w, lb + lh, ln - lh,
+ rb + rh, rn - rh,
+ k + lh + rh, g);
+ rn = rh;
+ ln = lh;
+ addToPendingCount(1);
+ m.fork();
}
- int l = lo;
- int lFence = l + nleft;
- int r = ro;
- int rFence = r + nright;
- int k = wo;
- while (l < lFence && r < rFence) {
- double al = a[l];
- double ar = a[r];
- double t;
- if (Double.compare(al, ar) <= 0) {
- ++l;
- t = al;
- } else {
- ++r;
- t = ar;
+ int lf = lb + ln, rf = rb + rn; // index bounds
+ while (lb < lf && rb < rf) {
+ double t, al, ar;
+ if ((al = a[lb]) <= (ar = a[rb])) {
+ lb++; t = al;
+ }
+ else {
+ rb++; t = ar;
}
w[k++] = t;
}
- while (l < lFence)
- w[k++] = a[l++];
- while (r < rFence)
- w[k++] = a[r++];
- while (rights != null) {
- if (rights.tryUnfork())
- rights.compute();
- else
- rights.join();
- rights = rights.next;
- }
+ if (rb < rf)
+ System.arraycopy(a, rb, w, k, rf - rb);
+ else if (lb < lf)
+ System.arraycopy(a, lb, w, k, lf - lb);
+ tryComplete();
}
}
} // FJDouble
- /** Comparable support class */
- static final class FJComparable {
- static final class Sorter<T extends Comparable<? super T>> extends RecursiveAction {
- static final long serialVersionUID = -1024003289463302522L;
- final T[] a;
- final T[] w;
- final int origin;
- final int n;
- final int gran;
-
- Sorter(T[] a, T[] w, int origin, int n, int gran) {
- this.a = a;
- this.w = w;
- this.origin = origin;
- this.n = n;
- this.gran = gran;
- }
-
- public void compute() {
- final int l = origin;
- final int g = gran;
- final int n = this.n;
- final T[] a = this.a;
- final T[] w = this.w;
- if (n > g) {
- int h = n >>> 1;
- int q = n >>> 2;
- int u = h + q;
- FJSubSorter ls = new FJSubSorter(new Sorter<>(a, w, l, q, g),
- new Sorter<>(a, w, l+q, h-q, g),
- new Merger<>(a, w, l, q,
- l+q, h-q, l, g, null));
- FJSubSorter rs = new FJSubSorter(new Sorter<>(a, w, l+h, q, g),
- new Sorter<>(a, w, l+u, n-u, g),
- new Merger<>(a, w, l+h, q,
- l+u, n-u, l+h, g, null));
- rs.fork();
- ls.compute();
- if (rs.tryUnfork()) rs.compute(); else rs.join();
- new Merger<>(w, a, l, h, l + h, n - h, l, g, null).compute();
- } else {
- Arrays.sort(a, l, l+n);
- }
- }
- }
-
- static final class Merger<T extends Comparable<? super T>> extends RecursiveAction {
- static final long serialVersionUID = -3989771675258379302L;
- final T[] a;
- final T[] w;
- final int lo;
- final int ln;
- final int ro;
- final int rn;
- final int wo;
- final int gran;
- final Merger<T> next;
-
- Merger(T[] a, T[] w, int lo, int ln, int ro, int rn, int wo,
- int gran, Merger<T> next) {
- this.a = a;
- this.w = w;
- this.lo = lo;
- this.ln = ln;
- this.ro = ro;
- this.rn = rn;
- this.wo = wo;
- this.gran = gran;
- this.next = next;
- }
-
- public void compute() {
- final T[] a = this.a;
- final T[] w = this.w;
- Merger<T> rights = null;
- int nleft = ln;
- int nright = rn;
- while (nleft > gran) {
- int lh = nleft >>> 1;
- int splitIndex = lo + lh;
- T split = a[splitIndex];
- int rl = 0;
- int rh = nright;
- while (rl < rh) {
- int mid = (rl + rh) >>> 1;
- if (split.compareTo(a[ro + mid]) <= 0)
- rh = mid;
- else
- rl = mid + 1;
- }
- (rights = new Merger<>(a, w, splitIndex, nleft-lh, ro+rh,
- nright-rh, wo+lh+rh, gran, rights)).fork();
- nleft = lh;
- nright = rh;
- }
-
- int l = lo;
- int lFence = l + nleft;
- int r = ro;
- int rFence = r + nright;
- int k = wo;
- while (l < lFence && r < rFence) {
- T al = a[l];
- T ar = a[r];
- T t;
- if (al.compareTo(ar) <= 0) {++l; t=al;} else {++r; t=ar; }
- w[k++] = t;
- }
- while (l < lFence)
- w[k++] = a[l++];
- while (r < rFence)
- w[k++] = a[r++];
- while (rights != null) {
- if (rights.tryUnfork())
- rights.compute();
- else
- rights.join();
- rights = rights.next;
- }
- }
- }
- } // FJComparable
-
- /** Object + Comparator support class */
- static final class FJComparator {
- static final class Sorter<T> extends RecursiveAction {
- static final long serialVersionUID = 9191600840025808581L;
- final T[] a; // array to be sorted.
- final T[] w; // workspace for merge
- final int origin; // origin of the part of array we deal with
- final int n; // Number of elements in (sub)arrays.
- final int gran; // split control
- final Comparator<? super T> cmp; // Comparator to use
-
- Sorter(T[] a, T[] w, int origin, int n, int gran, Comparator<? super T> cmp) {
- this.a = a;
- this.w = w;
- this.origin = origin;
- this.n = n;
- this.cmp = cmp;
- this.gran = gran;
- }
-
- public void compute() {
- final int l = origin;
- final int g = gran;
- final int n = this.n;
- final T[] a = this.a;
- final T[] w = this.w;
- if (n > g) {
- int h = n >>> 1; // half
- int q = n >>> 2; // lower quarter index
- int u = h + q; // upper quarter
- FJSubSorter ls = new FJSubSorter(new Sorter<>(a, w, l, q, g, cmp),
- new Sorter<>(a, w, l+q, h-q, g, cmp),
- new Merger<>(a, w, l, q,
- l+q, h-q, l, g, null, cmp));
- FJSubSorter rs = new FJSubSorter(new Sorter<>(a, w, l + h, q, g, cmp),
- new Sorter<>(a, w, l+u, n-u, g, cmp),
- new Merger<>(a, w, l+h, q,
- l+u, n-u, l+h, g, null, cmp));
- rs.fork();
- ls.compute();
- if (rs.tryUnfork()) rs.compute(); else rs.join();
- new Merger<>(w, a, l, h, l + h, n - h, l, g, null, cmp).compute();
- } else {
- Arrays.sort(a, l, l+n, cmp);
- }
- }
- }
-
- static final class Merger<T> extends RecursiveAction {
- static final long serialVersionUID = -2679539040379156203L;
- final T[] a;
- final T[] w;
- final int lo;
- final int ln;
- final int ro;
- final int rn;
- final int wo;
- final int gran;
- final Merger<T> next;
- final Comparator<? super T> cmp;
-
- Merger(T[] a, T[] w, int lo, int ln, int ro, int rn, int wo,
- int gran, Merger<T> next, Comparator<? super T> cmp) {
- this.a = a;
- this.w = w;
- this.lo = lo;
- this.ln = ln;
- this.ro = ro;
- this.rn = rn;
- this.wo = wo;
- this.gran = gran;
- this.next = next;
- this.cmp = cmp;
- }
-
- public void compute() {
- final T[] a = this.a;
- final T[] w = this.w;
- Merger<T> rights = null;
- int nleft = ln;
- int nright = rn;
- while (nleft > gran) {
- int lh = nleft >>> 1;
- int splitIndex = lo + lh;
- T split = a[splitIndex];
- int rl = 0;
- int rh = nright;
- while (rl < rh) {
- int mid = (rl + rh) >>> 1;
- if (cmp.compare(split, a[ro+mid]) <= 0)
- rh = mid;
- else
- rl = mid + 1;
- }
- (rights = new Merger<>(a, w, splitIndex, nleft-lh, ro+rh,
- nright-rh, wo+lh+rh, gran, rights, cmp)).fork();
- nleft = lh;
- nright = rh;
- }
-
- int l = lo;
- int lFence = l + nleft;
- int r = ro;
- int rFence = r + nright;
- int k = wo;
- while (l < lFence && r < rFence) {
- T al = a[l];
- T ar = a[r];
- T t;
- if (cmp.compare(al, ar) <= 0) {
- ++l;
- t = al;
- } else {
- ++r;
- t = ar;
- }
- w[k++] = t;
- }
- while (l < lFence)
- w[k++] = a[l++];
- while (r < rFence)
- w[k++] = a[r++];
- while (rights != null) {
- if (rights.tryUnfork())
- rights.compute();
- else
- rights.join();
- rights = rights.next;
- }
- }
- }
- } // FJComparator
-
- /** Utility class to sort half a partitioned array */
- private static final class FJSubSorter extends RecursiveAction {
- static final long serialVersionUID = 9159249695527935512L;
- final RecursiveAction left;
- final RecursiveAction right;
- final RecursiveAction merger;
-
- FJSubSorter(RecursiveAction left, RecursiveAction right,
- RecursiveAction merger) {
- this.left = left;
- this.right = right;
- this.merger = merger;
- }
-
- public void compute() {
- right.fork();
- left.invoke();
- right.join();
- merger.invoke();
- }
- }
}
--- a/jdk/src/share/classes/java/util/ComparableTimSort.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/ComparableTimSort.java Mon Jun 03 23:23:20 2013 -0700
@@ -86,9 +86,13 @@
private static final int INITIAL_TMP_STORAGE_LENGTH = 256;
/**
- * Temp storage for merges.
+ * Temp storage for merges. A workspace array may optionally be
+ * provided in constructor, and if so will be used as long as it
+ * is big enough.
*/
private Object[] tmp;
+ private int tmpBase; // base of tmp array slice
+ private int tmpLen; // length of tmp array slice
/**
* A stack of pending runs yet to be merged. Run i starts at
@@ -108,15 +112,27 @@
* Creates a TimSort instance to maintain the state of an ongoing sort.
*
* @param a the array to be sorted
+ * @param work a workspace array (slice)
+ * @param workBase origin of usable space in work array
+ * @param workLen usable size of work array
*/
- private ComparableTimSort(Object[] a) {
+ private ComparableTimSort(Object[] a, Object[] work, int workBase, int workLen) {
this.a = a;
// Allocate temp storage (which may be increased later if necessary)
int len = a.length;
- Object[] newArray = new Object[len < 2 * INITIAL_TMP_STORAGE_LENGTH ?
- len >>> 1 : INITIAL_TMP_STORAGE_LENGTH];
- tmp = newArray;
+ int tlen = (len < 2 * INITIAL_TMP_STORAGE_LENGTH) ?
+ len >>> 1 : INITIAL_TMP_STORAGE_LENGTH;
+ if (work == null || workLen < tlen || workBase + tlen > work.length) {
+ tmp = new Object[tlen];
+ tmpBase = 0;
+ tmpLen = tlen;
+ }
+ else {
+ tmp = work;
+ tmpBase = workBase;
+ tmpLen = workLen;
+ }
/*
* Allocate runs-to-be-merged stack (which cannot be expanded). The
@@ -136,17 +152,28 @@
}
/*
- * The next two methods (which are package private and static) constitute
- * the entire API of this class. Each of these methods obeys the contract
- * of the public method with the same signature in java.util.Arrays.
+ * The next method (package private and static) constitutes the
+ * entire API of this class.
*/
- static void sort(Object[] a) {
- sort(a, 0, a.length);
- }
+ /**
+ * Sorts the given range, using the given workspace array slice
+ * for temp storage when possible. This method is designed to be
+ * invoked from public methods (in class Arrays) after performing
+ * any necessary array bounds checks and expanding parameters into
+ * the required forms.
+ *
+ * @param a the array to be sorted
+ * @param lo the index of the first element, inclusive, to be sorted
+ * @param hi the index of the last element, exclusive, to be sorted
+ * @param work a workspace array (slice)
+ * @param workBase origin of usable space in work array
+ * @param workLen usable size of work array
+ * @since 1.8
+ */
+ static void sort(Object[] a, int lo, int hi, Object[] work, int workBase, int workLen) {
+ assert a != null && lo >= 0 && lo <= hi && hi <= a.length;
- static void sort(Object[] a, int lo, int hi) {
- rangeCheck(a.length, lo, hi);
int nRemaining = hi - lo;
if (nRemaining < 2)
return; // Arrays of size 0 and 1 are always sorted
@@ -163,7 +190,7 @@
* extending short natural runs to minRun elements, and merging runs
* to maintain stack invariant.
*/
- ComparableTimSort ts = new ComparableTimSort(a);
+ ComparableTimSort ts = new ComparableTimSort(a, work, workBase, workLen);
int minRun = minRunLength(nRemaining);
do {
// Identify next run
@@ -619,11 +646,11 @@
// Copy first run into temp array
Object[] a = this.a; // For performance
Object[] tmp = ensureCapacity(len1);
- System.arraycopy(a, base1, tmp, 0, len1);
- int cursor1 = 0; // Indexes into tmp array
+ int cursor1 = tmpBase; // Indexes into tmp array
int cursor2 = base2; // Indexes int a
int dest = base1; // Indexes int a
+ System.arraycopy(a, base1, tmp, cursor1, len1);
// Move first element of second run and deal with degenerate cases
a[dest++] = a[cursor2++];
@@ -736,16 +763,17 @@
// Copy second run into temp array
Object[] a = this.a; // For performance
Object[] tmp = ensureCapacity(len2);
- System.arraycopy(a, base2, tmp, 0, len2);
+ int tmpBase = this.tmpBase;
+ System.arraycopy(a, base2, tmp, tmpBase, len2);
int cursor1 = base1 + len1 - 1; // Indexes into a
- int cursor2 = len2 - 1; // Indexes into tmp array
+ int cursor2 = tmpBase + len2 - 1; // Indexes into tmp array
int dest = base2 + len2 - 1; // Indexes into a
// Move last element of first run and deal with degenerate cases
a[dest--] = a[cursor1--];
if (--len1 == 0) {
- System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2);
+ System.arraycopy(tmp, tmpBase, a, dest - (len2 - 1), len2);
return;
}
if (len2 == 1) {
@@ -803,7 +831,7 @@
if (--len2 == 1)
break outer;
- count2 = len2 - gallopLeft((Comparable) a[cursor1], tmp, 0, len2, len2 - 1);
+ count2 = len2 - gallopLeft((Comparable) a[cursor1], tmp, tmpBase, len2, len2 - 1);
if (count2 != 0) {
dest -= count2;
cursor2 -= count2;
@@ -835,7 +863,7 @@
} else {
assert len1 == 0;
assert len2 > 0;
- System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2);
+ System.arraycopy(tmp, tmpBase, a, dest - (len2 - 1), len2);
}
}
@@ -848,7 +876,7 @@
* @return tmp, whether or not it grew
*/
private Object[] ensureCapacity(int minCapacity) {
- if (tmp.length < minCapacity) {
+ if (tmpLen < minCapacity) {
// Compute smallest power of 2 > minCapacity
int newSize = minCapacity;
newSize |= newSize >> 1;
@@ -863,30 +891,13 @@
else
newSize = Math.min(newSize, a.length >>> 1);
+ @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
Object[] newArray = new Object[newSize];
tmp = newArray;
+ tmpLen = newSize;
+ tmpBase = 0;
}
return tmp;
}
- /**
- * Checks that fromIndex and toIndex are in range, and throws an
- * appropriate exception if they aren't.
- *
- * @param arrayLen the length of the array
- * @param fromIndex the index of the first element of the range
- * @param toIndex the index after the last element of the range
- * @throws IllegalArgumentException if fromIndex > toIndex
- * @throws ArrayIndexOutOfBoundsException if fromIndex < 0
- * or toIndex > arrayLen
- */
- private static void rangeCheck(int arrayLen, int fromIndex, int toIndex) {
- if (fromIndex > toIndex)
- throw new IllegalArgumentException("fromIndex(" + fromIndex +
- ") > toIndex(" + toIndex+")");
- if (fromIndex < 0)
- throw new ArrayIndexOutOfBoundsException(fromIndex);
- if (toIndex > arrayLen)
- throw new ArrayIndexOutOfBoundsException(toIndex);
- }
}
--- a/jdk/src/share/classes/java/util/DualPivotQuicksort.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/DualPivotQuicksort.java Mon Jun 03 23:23:20 2013 -0700
@@ -32,6 +32,11 @@
* quicksorts to degrade to quadratic performance, and is typically
* faster than traditional (one-pivot) Quicksort implementations.
*
+ * All exposed methods are package-private, designed to be invoked
+ * from public methods (in class Arrays) after performing any
+ * necessary array bounds checks and expanding parameters into the
+ * required forms.
+ *
* @author Vladimir Yaroslavskiy
* @author Jon Bentley
* @author Josh Bloch
@@ -89,22 +94,18 @@
*/
/**
- * Sorts the specified array.
- *
- * @param a the array to be sorted
- */
- public static void sort(int[] a) {
- sort(a, 0, a.length - 1);
- }
-
- /**
- * Sorts the specified range of the array.
+ * Sorts the specified range of the array using the given
+ * workspace array slice if possible for merging
*
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
+ * @param work a workspace array (slice)
+ * @param workBase origin of usable space in work array
+ * @param workLen usable size of work array
*/
- public static void sort(int[] a, int left, int right) {
+ static void sort(int[] a, int left, int right,
+ int[] work, int workBase, int workLen) {
// Use Quicksort on small arrays
if (right - left < QUICKSORT_THRESHOLD) {
sort(a, left, right, true);
@@ -147,24 +148,35 @@
}
// Check special cases
+ // Implementation note: variable "right" is increased by 1.
if (run[count] == right++) { // The last run contains one element
run[++count] = right;
} else if (count == 1) { // The array is already sorted
return;
}
- /*
- * Create temporary array, which is used for merging.
- * Implementation note: variable "right" is increased by 1.
- */
- int[] b; byte odd = 0;
+ // Determine alternation base for merge
+ byte odd = 0;
for (int n = 1; (n <<= 1) < count; odd ^= 1);
+ // Use or create temporary array b for merging
+ int[] b; // temp array; alternates with a
+ int ao, bo; // array offsets from 'left'
+ int blen = right - left; // space needed for b
+ if (work == null || workLen < blen || workBase + blen > work.length) {
+ work = new int[blen];
+ workBase = 0;
+ }
if (odd == 0) {
- b = a; a = new int[b.length];
- for (int i = left - 1; ++i < right; a[i] = b[i]);
+ System.arraycopy(a, left, work, workBase, blen);
+ b = a;
+ bo = 0;
+ a = work;
+ ao = workBase - left;
} else {
- b = new int[a.length];
+ b = work;
+ ao = 0;
+ bo = workBase - left;
}
// Merging
@@ -172,21 +184,22 @@
for (int k = (last = 0) + 2; k <= count; k += 2) {
int hi = run[k], mi = run[k - 1];
for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
- if (q >= hi || p < mi && a[p] <= a[q]) {
- b[i] = a[p++];
+ if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
+ b[i + bo] = a[p++ + ao];
} else {
- b[i] = a[q++];
+ b[i + bo] = a[q++ + ao];
}
}
run[++last] = hi;
}
if ((count & 1) != 0) {
for (int i = right, lo = run[count - 1]; --i >= lo;
- b[i] = a[i]
+ b[i + bo] = a[i + ao]
);
run[++last] = right;
}
int[] t = a; a = b; b = t;
+ int o = ao; ao = bo; bo = o;
}
}
@@ -529,22 +542,18 @@
}
/**
- * Sorts the specified array.
- *
- * @param a the array to be sorted
- */
- public static void sort(long[] a) {
- sort(a, 0, a.length - 1);
- }
-
- /**
- * Sorts the specified range of the array.
+ * Sorts the specified range of the array using the given
+ * workspace array slice if possible for merging
*
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
+ * @param work a workspace array (slice)
+ * @param workBase origin of usable space in work array
+ * @param workLen usable size of work array
*/
- public static void sort(long[] a, int left, int right) {
+ static void sort(long[] a, int left, int right,
+ long[] work, int workBase, int workLen) {
// Use Quicksort on small arrays
if (right - left < QUICKSORT_THRESHOLD) {
sort(a, left, right, true);
@@ -587,24 +596,35 @@
}
// Check special cases
+ // Implementation note: variable "right" is increased by 1.
if (run[count] == right++) { // The last run contains one element
run[++count] = right;
} else if (count == 1) { // The array is already sorted
return;
}
- /*
- * Create temporary array, which is used for merging.
- * Implementation note: variable "right" is increased by 1.
- */
- long[] b; byte odd = 0;
+ // Determine alternation base for merge
+ byte odd = 0;
for (int n = 1; (n <<= 1) < count; odd ^= 1);
+ // Use or create temporary array b for merging
+ long[] b; // temp array; alternates with a
+ int ao, bo; // array offsets from 'left'
+ int blen = right - left; // space needed for b
+ if (work == null || workLen < blen || workBase + blen > work.length) {
+ work = new long[blen];
+ workBase = 0;
+ }
if (odd == 0) {
- b = a; a = new long[b.length];
- for (int i = left - 1; ++i < right; a[i] = b[i]);
+ System.arraycopy(a, left, work, workBase, blen);
+ b = a;
+ bo = 0;
+ a = work;
+ ao = workBase - left;
} else {
- b = new long[a.length];
+ b = work;
+ ao = 0;
+ bo = workBase - left;
}
// Merging
@@ -612,21 +632,22 @@
for (int k = (last = 0) + 2; k <= count; k += 2) {
int hi = run[k], mi = run[k - 1];
for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
- if (q >= hi || p < mi && a[p] <= a[q]) {
- b[i] = a[p++];
+ if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
+ b[i + bo] = a[p++ + ao];
} else {
- b[i] = a[q++];
+ b[i + bo] = a[q++ + ao];
}
}
run[++last] = hi;
}
if ((count & 1) != 0) {
for (int i = right, lo = run[count - 1]; --i >= lo;
- b[i] = a[i]
+ b[i + bo] = a[i + ao]
);
run[++last] = right;
}
long[] t = a; a = b; b = t;
+ int o = ao; ao = bo; bo = o;
}
}
@@ -969,22 +990,18 @@
}
/**
- * Sorts the specified array.
- *
- * @param a the array to be sorted
- */
- public static void sort(short[] a) {
- sort(a, 0, a.length - 1);
- }
-
- /**
- * Sorts the specified range of the array.
+ * Sorts the specified range of the array using the given
+ * workspace array slice if possible for merging
*
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
+ * @param work a workspace array (slice)
+ * @param workBase origin of usable space in work array
+ * @param workLen usable size of work array
*/
- public static void sort(short[] a, int left, int right) {
+ static void sort(short[] a, int left, int right,
+ short[] work, int workBase, int workLen) {
// Use counting sort on large arrays
if (right - left > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
int[] count = new int[NUM_SHORT_VALUES];
@@ -1002,7 +1019,7 @@
} while (--s > 0);
}
} else { // Use Dual-Pivot Quicksort on small arrays
- doSort(a, left, right);
+ doSort(a, left, right, work, workBase, workLen);
}
}
@@ -1015,8 +1032,12 @@
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
+ * @param work a workspace array (slice)
+ * @param workBase origin of usable space in work array
+ * @param workLen usable size of work array
*/
- private static void doSort(short[] a, int left, int right) {
+ private static void doSort(short[] a, int left, int right,
+ short[] work, int workBase, int workLen) {
// Use Quicksort on small arrays
if (right - left < QUICKSORT_THRESHOLD) {
sort(a, left, right, true);
@@ -1059,24 +1080,35 @@
}
// Check special cases
+ // Implementation note: variable "right" is increased by 1.
if (run[count] == right++) { // The last run contains one element
run[++count] = right;
} else if (count == 1) { // The array is already sorted
return;
}
- /*
- * Create temporary array, which is used for merging.
- * Implementation note: variable "right" is increased by 1.
- */
- short[] b; byte odd = 0;
+ // Determine alternation base for merge
+ byte odd = 0;
for (int n = 1; (n <<= 1) < count; odd ^= 1);
+ // Use or create temporary array b for merging
+ short[] b; // temp array; alternates with a
+ int ao, bo; // array offsets from 'left'
+ int blen = right - left; // space needed for b
+ if (work == null || workLen < blen || workBase + blen > work.length) {
+ work = new short[blen];
+ workBase = 0;
+ }
if (odd == 0) {
- b = a; a = new short[b.length];
- for (int i = left - 1; ++i < right; a[i] = b[i]);
+ System.arraycopy(a, left, work, workBase, blen);
+ b = a;
+ bo = 0;
+ a = work;
+ ao = workBase - left;
} else {
- b = new short[a.length];
+ b = work;
+ ao = 0;
+ bo = workBase - left;
}
// Merging
@@ -1084,21 +1116,22 @@
for (int k = (last = 0) + 2; k <= count; k += 2) {
int hi = run[k], mi = run[k - 1];
for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
- if (q >= hi || p < mi && a[p] <= a[q]) {
- b[i] = a[p++];
+ if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
+ b[i + bo] = a[p++ + ao];
} else {
- b[i] = a[q++];
+ b[i + bo] = a[q++ + ao];
}
}
run[++last] = hi;
}
if ((count & 1) != 0) {
for (int i = right, lo = run[count - 1]; --i >= lo;
- b[i] = a[i]
+ b[i + bo] = a[i + ao]
);
run[++last] = right;
}
short[] t = a; a = b; b = t;
+ int o = ao; ao = bo; bo = o;
}
}
@@ -1441,22 +1474,18 @@
}
/**
- * Sorts the specified array.
- *
- * @param a the array to be sorted
- */
- public static void sort(char[] a) {
- sort(a, 0, a.length - 1);
- }
-
- /**
- * Sorts the specified range of the array.
+ * Sorts the specified range of the array using the given
+ * workspace array slice if possible for merging
*
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
+ * @param work a workspace array (slice)
+ * @param workBase origin of usable space in work array
+ * @param workLen usable size of work array
*/
- public static void sort(char[] a, int left, int right) {
+ static void sort(char[] a, int left, int right,
+ char[] work, int workBase, int workLen) {
// Use counting sort on large arrays
if (right - left > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
int[] count = new int[NUM_CHAR_VALUES];
@@ -1474,7 +1503,7 @@
} while (--s > 0);
}
} else { // Use Dual-Pivot Quicksort on small arrays
- doSort(a, left, right);
+ doSort(a, left, right, work, workBase, workLen);
}
}
@@ -1487,8 +1516,12 @@
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
+ * @param work a workspace array (slice)
+ * @param workBase origin of usable space in work array
+ * @param workLen usable size of work array
*/
- private static void doSort(char[] a, int left, int right) {
+ private static void doSort(char[] a, int left, int right,
+ char[] work, int workBase, int workLen) {
// Use Quicksort on small arrays
if (right - left < QUICKSORT_THRESHOLD) {
sort(a, left, right, true);
@@ -1531,24 +1564,35 @@
}
// Check special cases
+ // Implementation note: variable "right" is increased by 1.
if (run[count] == right++) { // The last run contains one element
run[++count] = right;
} else if (count == 1) { // The array is already sorted
return;
}
- /*
- * Create temporary array, which is used for merging.
- * Implementation note: variable "right" is increased by 1.
- */
- char[] b; byte odd = 0;
+ // Determine alternation base for merge
+ byte odd = 0;
for (int n = 1; (n <<= 1) < count; odd ^= 1);
+ // Use or create temporary array b for merging
+ char[] b; // temp array; alternates with a
+ int ao, bo; // array offsets from 'left'
+ int blen = right - left; // space needed for b
+ if (work == null || workLen < blen || workBase + blen > work.length) {
+ work = new char[blen];
+ workBase = 0;
+ }
if (odd == 0) {
- b = a; a = new char[b.length];
- for (int i = left - 1; ++i < right; a[i] = b[i]);
+ System.arraycopy(a, left, work, workBase, blen);
+ b = a;
+ bo = 0;
+ a = work;
+ ao = workBase - left;
} else {
- b = new char[a.length];
+ b = work;
+ ao = 0;
+ bo = workBase - left;
}
// Merging
@@ -1556,21 +1600,22 @@
for (int k = (last = 0) + 2; k <= count; k += 2) {
int hi = run[k], mi = run[k - 1];
for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
- if (q >= hi || p < mi && a[p] <= a[q]) {
- b[i] = a[p++];
+ if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
+ b[i + bo] = a[p++ + ao];
} else {
- b[i] = a[q++];
+ b[i + bo] = a[q++ + ao];
}
}
run[++last] = hi;
}
if ((count & 1) != 0) {
for (int i = right, lo = run[count - 1]; --i >= lo;
- b[i] = a[i]
+ b[i + bo] = a[i + ao]
);
run[++last] = right;
}
char[] t = a; a = b; b = t;
+ int o = ao; ao = bo; bo = o;
}
}
@@ -1916,22 +1961,13 @@
private static final int NUM_BYTE_VALUES = 1 << 8;
/**
- * Sorts the specified array.
- *
- * @param a the array to be sorted
- */
- public static void sort(byte[] a) {
- sort(a, 0, a.length - 1);
- }
-
- /**
* Sorts the specified range of the array.
*
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
*/
- public static void sort(byte[] a, int left, int right) {
+ static void sort(byte[] a, int left, int right) {
// Use counting sort on large arrays
if (right - left > COUNTING_SORT_THRESHOLD_FOR_BYTE) {
int[] count = new int[NUM_BYTE_VALUES];
@@ -1963,22 +1999,18 @@
}
/**
- * Sorts the specified array.
- *
- * @param a the array to be sorted
- */
- public static void sort(float[] a) {
- sort(a, 0, a.length - 1);
- }
-
- /**
- * Sorts the specified range of the array.
+ * Sorts the specified range of the array using the given
+ * workspace array slice if possible for merging
*
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
+ * @param work a workspace array (slice)
+ * @param workBase origin of usable space in work array
+ * @param workLen usable size of work array
*/
- public static void sort(float[] a, int left, int right) {
+ static void sort(float[] a, int left, int right,
+ float[] work, int workBase, int workLen) {
/*
* Phase 1: Move NaNs to the end of the array.
*/
@@ -1997,7 +2029,7 @@
/*
* Phase 2: Sort everything except NaNs (which are already in place).
*/
- doSort(a, left, right);
+ doSort(a, left, right, work, workBase, workLen);
/*
* Phase 3: Place negative zeros before positive zeros.
@@ -2064,8 +2096,12 @@
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
+ * @param work a workspace array (slice)
+ * @param workBase origin of usable space in work array
+ * @param workLen usable size of work array
*/
- private static void doSort(float[] a, int left, int right) {
+ private static void doSort(float[] a, int left, int right,
+ float[] work, int workBase, int workLen) {
// Use Quicksort on small arrays
if (right - left < QUICKSORT_THRESHOLD) {
sort(a, left, right, true);
@@ -2108,24 +2144,35 @@
}
// Check special cases
+ // Implementation note: variable "right" is increased by 1.
if (run[count] == right++) { // The last run contains one element
run[++count] = right;
} else if (count == 1) { // The array is already sorted
return;
}
- /*
- * Create temporary array, which is used for merging.
- * Implementation note: variable "right" is increased by 1.
- */
- float[] b; byte odd = 0;
+ // Determine alternation base for merge
+ byte odd = 0;
for (int n = 1; (n <<= 1) < count; odd ^= 1);
+ // Use or create temporary array b for merging
+ float[] b; // temp array; alternates with a
+ int ao, bo; // array offsets from 'left'
+ int blen = right - left; // space needed for b
+ if (work == null || workLen < blen || workBase + blen > work.length) {
+ work = new float[blen];
+ workBase = 0;
+ }
if (odd == 0) {
- b = a; a = new float[b.length];
- for (int i = left - 1; ++i < right; a[i] = b[i]);
+ System.arraycopy(a, left, work, workBase, blen);
+ b = a;
+ bo = 0;
+ a = work;
+ ao = workBase - left;
} else {
- b = new float[a.length];
+ b = work;
+ ao = 0;
+ bo = workBase - left;
}
// Merging
@@ -2133,21 +2180,22 @@
for (int k = (last = 0) + 2; k <= count; k += 2) {
int hi = run[k], mi = run[k - 1];
for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
- if (q >= hi || p < mi && a[p] <= a[q]) {
- b[i] = a[p++];
+ if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
+ b[i + bo] = a[p++ + ao];
} else {
- b[i] = a[q++];
+ b[i + bo] = a[q++ + ao];
}
}
run[++last] = hi;
}
if ((count & 1) != 0) {
for (int i = right, lo = run[count - 1]; --i >= lo;
- b[i] = a[i]
+ b[i + bo] = a[i + ao]
);
run[++last] = right;
}
float[] t = a; a = b; b = t;
+ int o = ao; ao = bo; bo = o;
}
}
@@ -2490,22 +2538,18 @@
}
/**
- * Sorts the specified array.
- *
- * @param a the array to be sorted
- */
- public static void sort(double[] a) {
- sort(a, 0, a.length - 1);
- }
-
- /**
- * Sorts the specified range of the array.
+ * Sorts the specified range of the array using the given
+ * workspace array slice if possible for merging
*
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
+ * @param work a workspace array (slice)
+ * @param workBase origin of usable space in work array
+ * @param workLen usable size of work array
*/
- public static void sort(double[] a, int left, int right) {
+ static void sort(double[] a, int left, int right,
+ double[] work, int workBase, int workLen) {
/*
* Phase 1: Move NaNs to the end of the array.
*/
@@ -2524,7 +2568,7 @@
/*
* Phase 2: Sort everything except NaNs (which are already in place).
*/
- doSort(a, left, right);
+ doSort(a, left, right, work, workBase, workLen);
/*
* Phase 3: Place negative zeros before positive zeros.
@@ -2591,8 +2635,12 @@
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
+ * @param work a workspace array (slice)
+ * @param workBase origin of usable space in work array
+ * @param workLen usable size of work array
*/
- private static void doSort(double[] a, int left, int right) {
+ private static void doSort(double[] a, int left, int right,
+ double[] work, int workBase, int workLen) {
// Use Quicksort on small arrays
if (right - left < QUICKSORT_THRESHOLD) {
sort(a, left, right, true);
@@ -2635,24 +2683,35 @@
}
// Check special cases
+ // Implementation note: variable "right" is increased by 1.
if (run[count] == right++) { // The last run contains one element
run[++count] = right;
} else if (count == 1) { // The array is already sorted
return;
}
- /*
- * Create temporary array, which is used for merging.
- * Implementation note: variable "right" is increased by 1.
- */
- double[] b; byte odd = 0;
+ // Determine alternation base for merge
+ byte odd = 0;
for (int n = 1; (n <<= 1) < count; odd ^= 1);
+ // Use or create temporary array b for merging
+ double[] b; // temp array; alternates with a
+ int ao, bo; // array offsets from 'left'
+ int blen = right - left; // space needed for b
+ if (work == null || workLen < blen || workBase + blen > work.length) {
+ work = new double[blen];
+ workBase = 0;
+ }
if (odd == 0) {
- b = a; a = new double[b.length];
- for (int i = left - 1; ++i < right; a[i] = b[i]);
+ System.arraycopy(a, left, work, workBase, blen);
+ b = a;
+ bo = 0;
+ a = work;
+ ao = workBase - left;
} else {
- b = new double[a.length];
+ b = work;
+ ao = 0;
+ bo = workBase - left;
}
// Merging
@@ -2660,21 +2719,22 @@
for (int k = (last = 0) + 2; k <= count; k += 2) {
int hi = run[k], mi = run[k - 1];
for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
- if (q >= hi || p < mi && a[p] <= a[q]) {
- b[i] = a[p++];
+ if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
+ b[i + bo] = a[p++ + ao];
} else {
- b[i] = a[q++];
+ b[i + bo] = a[q++ + ao];
}
}
run[++last] = hi;
}
if ((count & 1) != 0) {
for (int i = right, lo = run[count - 1]; --i >= lo;
- b[i] = a[i]
+ b[i + bo] = a[i + ao]
);
run[++last] = right;
}
double[] t = a; a = b; b = t;
+ int o = ao; ao = bo; bo = o;
}
}
--- a/jdk/src/share/classes/java/util/ListResourceBundle.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/ListResourceBundle.java Mon Jun 03 23:23:20 2013 -0700
@@ -89,7 +89,7 @@
*
* public class MyResources_fr extends ListResourceBundle {
* protected Object[][] getContents() {
- * return new Object[][] = {
+ * return new Object[][] {
* // LOCALIZE THIS
* {"s1", "Le disque \"{1}\" {0}."}, // MessageFormat pattern
* {"s2", "1"}, // location of {0} in pattern
--- a/jdk/src/share/classes/java/util/PropertyResourceBundle.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/PropertyResourceBundle.java Mon Jun 03 23:23:20 2013 -0700
@@ -124,6 +124,8 @@
* to read from.
* @throws IOException if an I/O error occurs
* @throws NullPointerException if <code>stream</code> is null
+ * @throws IllegalArgumentException if {@code stream} contains a
+ * malformed Unicode escape sequence.
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public PropertyResourceBundle (InputStream stream) throws IOException {
@@ -142,6 +144,8 @@
* read from.
* @throws IOException if an I/O error occurs
* @throws NullPointerException if <code>reader</code> is null
+ * @throws IllegalArgumentException if a malformed Unicode escape sequence appears
+ * from {@code reader}.
* @since 1.6
*/
@SuppressWarnings({"unchecked", "rawtypes"})
--- a/jdk/src/share/classes/java/util/Spliterator.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/Spliterator.java Mon Jun 03 23:23:20 2013 -0700
@@ -140,32 +140,32 @@
* (in approximate order of decreasing desirability):
* <ul>
* <li>The source cannot be structurally interfered with.
- * </br>For example, an instance of
+ * <br>For example, an instance of
* {@link java.util.concurrent.CopyOnWriteArrayList} is an immutable source.
* A Spliterator created from the source reports a characteristic of
* {@code IMMUTABLE}.</li>
* <li>The source manages concurrent modifications.
- * </br>For example, a key set of a {@link java.util.concurrent.ConcurrentHashMap}
+ * <br>For example, a key set of a {@link java.util.concurrent.ConcurrentHashMap}
* is a concurrent source. A Spliterator created from the source reports a
* characteristic of {@code CONCURRENT}.</li>
* <li>The mutable source provides a late-binding and fail-fast Spliterator.
- * </br>Late binding narrows the window during which interference can affect
+ * <br>Late binding narrows the window during which interference can affect
* the calculation; fail-fast detects, on a best-effort basis, that structural
* interference has occurred after traversal has commenced and throws
* {@link ConcurrentModificationException}. For example, {@link ArrayList},
* and many other non-concurrent {@code Collection} classes in the JDK, provide
* a late-binding, fail-fast spliterator.</li>
* <li>The mutable source provides a non-late-binding but fail-fast Spliterator.
- * </br>The source increases the likelihood of throwing
+ * <br>The source increases the likelihood of throwing
* {@code ConcurrentModificationException} since the window of potential
* interference is larger.</li>
* <li>The mutable source provides a late-binding and non-fail-fast Spliterator.
- * </br>The source risks arbitrary, non-deterministic behavior after traversal
+ * <br>The source risks arbitrary, non-deterministic behavior after traversal
* has commenced since interference is not detected.
* </li>
* <li>The mutable source provides a non-late-binding and non-fail-fast
* Spliterator.
- * </br>The source increases the risk of arbitrary, non-deterministic behavior
+ * <br>The source increases the risk of arbitrary, non-deterministic behavior
* since non-detected interference may occur after construction.
* </li>
* </ul>
@@ -284,6 +284,8 @@
* is set to {@code true} then diagnostic warnings are reported if boxing of
* primitive values occur when operating on primitive subtype specializations.
*
+ * @param <T> the type of elements returned by this Spliterator
+ *
* @see Collection
* @since 1.8
*/
@@ -333,9 +335,8 @@
* Upon non-null return:
* <ul>
* <li>the value reported for {@code estimateSize()} before splitting,
- * if not already zero or {@code Long.MAX_VALUE}, must, after splitting, be
- * greater than {@code estimateSize()} for this and the returned
- * Spliterator; and</li>
+ * must, after splitting, be greater than or equal to {@code estimateSize()}
+ * for this and the returned Spliterator; and</li>
* <li>if this Spliterator is {@code SUBSIZED}, then {@code estimateSize()}
* for this spliterator before splitting must be equal to the sum of
* {@code estimateSize()} for this and the returned Spliterator after
@@ -566,13 +567,28 @@
public static final int SUBSIZED = 0x00004000;
/**
- * A Spliterator specialized for {@code int} values.
+ * A Spliterator specialized for primitive values.
+ *
+ * @param <T> the type of elements returned by this Spliterator. The
+ * type must be a wrapper type for a primitive type, such as {@code Integer}
+ * for the primitive {@code int} type.
+ * @param <T_CONS> the type of primitive consumer. The type must be a
+ * primitive specialization of {@link java.util.function.Consumer} for
+ * {@code T}, such as {@link java.util.function.IntConsumer} for
+ * {@code Integer}.
+ * @param <T_SPLITR> the type of primitive Spliterator. The type must be
+ * a primitive specialization of Spliterator for {@code T}, such as
+ * {@link Spliterator.OfInt} for {@code Integer}.
+ *
+ * @see Spliterator.OfInt
+ * @see Spliterator.OfLong
+ * @see Spliterator.OfDouble
* @since 1.8
*/
- public interface OfInt extends Spliterator<Integer> {
-
+ public interface OfPrimitive<T, T_CONS, T_SPLITR extends Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>>
+ extends Spliterator<T> {
@Override
- OfInt trySplit();
+ T_SPLITR trySplit();
/**
* If a remaining element exists, performs the given action on it,
@@ -586,7 +602,7 @@
* upon entry to this method, else {@code true}.
* @throws NullPointerException if the specified action is null
*/
- boolean tryAdvance(IntConsumer action);
+ boolean tryAdvance(T_CONS action);
/**
* Performs the given action for each remaining element, sequentially in
@@ -603,6 +619,24 @@
* @param action The action
* @throws NullPointerException if the specified action is null
*/
+ default void forEachRemaining(T_CONS action) {
+ do { } while (tryAdvance(action));
+ }
+ }
+
+ /**
+ * A Spliterator specialized for {@code int} values.
+ * @since 1.8
+ */
+ public interface OfInt extends OfPrimitive<Integer, IntConsumer, OfInt> {
+
+ @Override
+ OfInt trySplit();
+
+ @Override
+ boolean tryAdvance(IntConsumer action);
+
+ @Override
default void forEachRemaining(IntConsumer action) {
do { } while (tryAdvance(action));
}
@@ -658,40 +692,15 @@
* A Spliterator specialized for {@code long} values.
* @since 1.8
*/
- public interface OfLong extends Spliterator<Long> {
+ public interface OfLong extends OfPrimitive<Long, LongConsumer, OfLong> {
@Override
OfLong trySplit();
- /**
- * If a remaining element exists, performs the given action on it,
- * returning {@code true}; else returns {@code false}. If this
- * Spliterator is {@link #ORDERED} the action is performed on the
- * next element in encounter order. Exceptions thrown by the
- * action are relayed to the caller.
- *
- * @param action The action
- * @return {@code false} if no remaining elements existed
- * upon entry to this method, else {@code true}.
- * @throws NullPointerException if the specified action is null
- */
+ @Override
boolean tryAdvance(LongConsumer action);
- /**
- * Performs the given action for each remaining element, sequentially in
- * the current thread, until all elements have been processed or the
- * action throws an exception. If this Spliterator is {@link #ORDERED},
- * actions are performed in encounter order. Exceptions thrown by the
- * action are relayed to the caller.
- *
- * @implSpec
- * The default implementation repeatedly invokes {@link #tryAdvance}
- * until it returns {@code false}. It should be overridden whenever
- * possible.
- *
- * @param action The action
- * @throws NullPointerException if the specified action is null
- */
+ @Override
default void forEachRemaining(LongConsumer action) {
do { } while (tryAdvance(action));
}
@@ -747,40 +756,15 @@
* A Spliterator specialized for {@code double} values.
* @since 1.8
*/
- public interface OfDouble extends Spliterator<Double> {
+ public interface OfDouble extends OfPrimitive<Double, DoubleConsumer, OfDouble> {
@Override
OfDouble trySplit();
- /**
- * If a remaining element exists, performs the given action on it,
- * returning {@code true}; else returns {@code false}. If this
- * Spliterator is {@link #ORDERED} the action is performed on the
- * next element in encounter order. Exceptions thrown by the
- * action are relayed to the caller.
- *
- * @param action The action
- * @return {@code false} if no remaining elements existed
- * upon entry to this method, else {@code true}.
- * @throws NullPointerException if the specified action is null
- */
+ @Override
boolean tryAdvance(DoubleConsumer action);
- /**
- * Performs the given action for each remaining element, sequentially in
- * the current thread, until all elements have been processed or the
- * action throws an exception. If this Spliterator is {@link #ORDERED},
- * actions are performed in encounter order. Exceptions thrown by the
- * action are relayed to the caller.
- *
- * @implSpec
- * The default implementation repeatedly invokes {@link #tryAdvance}
- * until it returns {@code false}. It should be overridden whenever
- * possible.
- *
- * @param action The action
- * @throws NullPointerException if the specified action is null
- */
+ @Override
default void forEachRemaining(DoubleConsumer action) {
do { } while (tryAdvance(action));
}
--- a/jdk/src/share/classes/java/util/TimSort.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/TimSort.java Mon Jun 03 23:23:20 2013 -0700
@@ -111,9 +111,13 @@
private static final int INITIAL_TMP_STORAGE_LENGTH = 256;
/**
- * Temp storage for merges.
+ * Temp storage for merges. A workspace array may optionally be
+ * provided in constructor, and if so will be used as long as it
+ * is big enough.
*/
- private T[] tmp; // Actual runtime type will be Object[], regardless of T
+ private T[] tmp;
+ private int tmpBase; // base of tmp array slice
+ private int tmpLen; // length of tmp array slice
/**
* A stack of pending runs yet to be merged. Run i starts at
@@ -134,17 +138,31 @@
*
* @param a the array to be sorted
* @param c the comparator to determine the order of the sort
+ * @param work a workspace array (slice)
+ * @param workBase origin of usable space in work array
+ * @param workLen usable size of work array
*/
- private TimSort(T[] a, Comparator<? super T> c) {
+ private TimSort(T[] a, Comparator<? super T> c, T[] work, int workBase, int workLen) {
this.a = a;
this.c = c;
// Allocate temp storage (which may be increased later if necessary)
int len = a.length;
- @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
- T[] newArray = (T[]) new Object[len < 2 * INITIAL_TMP_STORAGE_LENGTH ?
- len >>> 1 : INITIAL_TMP_STORAGE_LENGTH];
- tmp = newArray;
+ int tlen = (len < 2 * INITIAL_TMP_STORAGE_LENGTH) ?
+ len >>> 1 : INITIAL_TMP_STORAGE_LENGTH;
+ if (work == null || workLen < tlen || workBase + tlen > work.length) {
+ @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
+ T[] newArray = (T[])java.lang.reflect.Array.newInstance
+ (a.getClass().getComponentType(), tlen);
+ tmp = newArray;
+ tmpBase = 0;
+ tmpLen = tlen;
+ }
+ else {
+ tmp = work;
+ tmpBase = workBase;
+ tmpLen = workLen;
+ }
/*
* Allocate runs-to-be-merged stack (which cannot be expanded). The
@@ -164,22 +182,30 @@
}
/*
- * The next two methods (which are package private and static) constitute
- * the entire API of this class. Each of these methods obeys the contract
- * of the public method with the same signature in java.util.Arrays.
+ * The next method (package private and static) constitutes the
+ * entire API of this class.
*/
- static <T> void sort(T[] a, Comparator<? super T> c) {
- sort(a, 0, a.length, c);
- }
+ /**
+ * Sorts the given range, using the given workspace array slice
+ * for temp storage when possible. This method is designed to be
+ * invoked from public methods (in class Arrays) after performing
+ * any necessary array bounds checks and expanding parameters into
+ * the required forms.
+ *
+ * @param a the array to be sorted
+ * @param lo the index of the first element, inclusive, to be sorted
+ * @param hi the index of the last element, exclusive, to be sorted
+ * @param c the comparator to use
+ * @param work a workspace array (slice)
+ * @param workBase origin of usable space in work array
+ * @param workLen usable size of work array
+ * @since 1.8
+ */
+ static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c,
+ T[] work, int workBase, int workLen) {
+ assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length;
- static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c) {
- if (c == null) {
- Arrays.sort(a, lo, hi);
- return;
- }
-
- rangeCheck(a.length, lo, hi);
int nRemaining = hi - lo;
if (nRemaining < 2)
return; // Arrays of size 0 and 1 are always sorted
@@ -196,7 +222,7 @@
* extending short natural runs to minRun elements, and merging runs
* to maintain stack invariant.
*/
- TimSort<T> ts = new TimSort<>(a, c);
+ TimSort<T> ts = new TimSort<>(a, c, work, workBase, workLen);
int minRun = minRunLength(nRemaining);
do {
// Identify next run
@@ -653,11 +679,10 @@
// Copy first run into temp array
T[] a = this.a; // For performance
T[] tmp = ensureCapacity(len1);
- System.arraycopy(a, base1, tmp, 0, len1);
-
- int cursor1 = 0; // Indexes into tmp array
+ int cursor1 = tmpBase; // Indexes into tmp array
int cursor2 = base2; // Indexes int a
int dest = base1; // Indexes int a
+ System.arraycopy(a, base1, tmp, cursor1, len1);
// Move first element of second run and deal with degenerate cases
a[dest++] = a[cursor2++];
@@ -770,16 +795,17 @@
// Copy second run into temp array
T[] a = this.a; // For performance
T[] tmp = ensureCapacity(len2);
- System.arraycopy(a, base2, tmp, 0, len2);
+ int tmpBase = this.tmpBase;
+ System.arraycopy(a, base2, tmp, tmpBase, len2);
int cursor1 = base1 + len1 - 1; // Indexes into a
- int cursor2 = len2 - 1; // Indexes into tmp array
+ int cursor2 = tmpBase + len2 - 1; // Indexes into tmp array
int dest = base2 + len2 - 1; // Indexes into a
// Move last element of first run and deal with degenerate cases
a[dest--] = a[cursor1--];
if (--len1 == 0) {
- System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2);
+ System.arraycopy(tmp, tmpBase, a, dest - (len2 - 1), len2);
return;
}
if (len2 == 1) {
@@ -838,7 +864,7 @@
if (--len2 == 1)
break outer;
- count2 = len2 - gallopLeft(a[cursor1], tmp, 0, len2, len2 - 1, c);
+ count2 = len2 - gallopLeft(a[cursor1], tmp, tmpBase, len2, len2 - 1, c);
if (count2 != 0) {
dest -= count2;
cursor2 -= count2;
@@ -870,7 +896,7 @@
} else {
assert len1 == 0;
assert len2 > 0;
- System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2);
+ System.arraycopy(tmp, tmpBase, a, dest - (len2 - 1), len2);
}
}
@@ -883,7 +909,7 @@
* @return tmp, whether or not it grew
*/
private T[] ensureCapacity(int minCapacity) {
- if (tmp.length < minCapacity) {
+ if (tmpLen < minCapacity) {
// Compute smallest power of 2 > minCapacity
int newSize = minCapacity;
newSize |= newSize >> 1;
@@ -899,30 +925,12 @@
newSize = Math.min(newSize, a.length >>> 1);
@SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
- T[] newArray = (T[]) new Object[newSize];
+ T[] newArray = (T[])java.lang.reflect.Array.newInstance
+ (a.getClass().getComponentType(), newSize);
tmp = newArray;
+ tmpLen = newSize;
+ tmpBase = 0;
}
return tmp;
}
-
- /**
- * Checks that fromIndex and toIndex are in range, and throws an
- * appropriate exception if they aren't.
- *
- * @param arrayLen the length of the array
- * @param fromIndex the index of the first element of the range
- * @param toIndex the index after the last element of the range
- * @throws IllegalArgumentException if fromIndex > toIndex
- * @throws ArrayIndexOutOfBoundsException if fromIndex < 0
- * or toIndex > arrayLen
- */
- private static void rangeCheck(int arrayLen, int fromIndex, int toIndex) {
- if (fromIndex > toIndex)
- throw new IllegalArgumentException("fromIndex(" + fromIndex +
- ") > toIndex(" + toIndex+")");
- if (fromIndex < 0)
- throw new ArrayIndexOutOfBoundsException(fromIndex);
- if (toIndex > arrayLen)
- throw new ArrayIndexOutOfBoundsException(toIndex);
- }
}
--- a/jdk/src/share/classes/java/util/concurrent/ConcurrentHashMap.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/ConcurrentHashMap.java Mon Jun 03 23:23:20 2013 -0700
@@ -44,19 +44,19 @@
* adjustable expected concurrency for updates. This class obeys the
* same functional specification as {@link java.util.Hashtable}, and
* includes versions of methods corresponding to each method of
- * <tt>Hashtable</tt>. However, even though all operations are
+ * {@code Hashtable}. However, even though all operations are
* thread-safe, retrieval operations do <em>not</em> entail locking,
* and there is <em>not</em> any support for locking the entire table
* in a way that prevents all access. This class is fully
- * interoperable with <tt>Hashtable</tt> in programs that rely on its
+ * interoperable with {@code Hashtable} in programs that rely on its
* thread safety but not on its synchronization details.
*
- * <p> Retrieval operations (including <tt>get</tt>) generally do not
+ * <p> Retrieval operations (including {@code get}) generally do not
* block, so may overlap with update operations (including
- * <tt>put</tt> and <tt>remove</tt>). Retrievals reflect the results
+ * {@code put} and {@code remove}). Retrievals reflect the results
* of the most recently <em>completed</em> update operations holding
- * upon their onset. For aggregate operations such as <tt>putAll</tt>
- * and <tt>clear</tt>, concurrent retrievals may reflect insertion or
+ * upon their onset. For aggregate operations such as {@code putAll}
+ * and {@code clear}, concurrent retrievals may reflect insertion or
* removal of only some entries. Similarly, Iterators and
* Enumerations return elements reflecting the state of the hash table
* at some point at or since the creation of the iterator/enumeration.
@@ -64,8 +64,8 @@
* However, iterators are designed to be used by only one thread at a time.
*
* <p> The allowed concurrency among update operations is guided by
- * the optional <tt>concurrencyLevel</tt> constructor argument
- * (default <tt>16</tt>), which is used as a hint for internal sizing. The
+ * the optional {@code concurrencyLevel} constructor argument
+ * (default {@code 16}), which is used as a hint for internal sizing. The
* table is internally partitioned to try to permit the indicated
* number of concurrent updates without contention. Because placement
* in hash tables is essentially random, the actual concurrency will
@@ -85,8 +85,8 @@
* <em>optional</em> methods of the {@link Map} and {@link Iterator}
* interfaces.
*
- * <p> Like {@link Hashtable} but unlike {@link HashMap}, this class
- * does <em>not</em> allow <tt>null</tt> to be used as a key or value.
+ * <p>Like {@link Hashtable} but unlike {@link HashMap}, this class
+ * does <em>not</em> allow {@code null} to be used as a key or value.
*
* <p>This class is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
@@ -353,8 +353,8 @@
/**
* The table is rehashed when its size exceeds this threshold.
- * (The value of this field is always <tt>(int)(capacity *
- * loadFactor)</tt>.)
+ * (The value of this field is always {@code (int)(capacity *
+ * loadFactor)}.)
*/
transient int threshold;
@@ -829,9 +829,9 @@
}
/**
- * Returns <tt>true</tt> if this map contains no key-value mappings.
+ * Returns {@code true} if this map contains no key-value mappings.
*
- * @return <tt>true</tt> if this map contains no key-value mappings
+ * @return {@code true} if this map contains no key-value mappings
*/
public boolean isEmpty() {
/*
@@ -870,8 +870,8 @@
/**
* Returns the number of key-value mappings in this map. If the
- * map contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
- * <tt>Integer.MAX_VALUE</tt>.
+ * map contains more than {@code Integer.MAX_VALUE} elements, returns
+ * {@code Integer.MAX_VALUE}.
*
* @return the number of key-value mappings in this map
*/
@@ -948,10 +948,10 @@
/**
* Tests if the specified object is a key in this table.
*
- * @param key possible key
- * @return <tt>true</tt> if and only if the specified object
+ * @param key possible key
+ * @return {@code true} if and only if the specified object
* is a key in this table, as determined by the
- * <tt>equals</tt> method; <tt>false</tt> otherwise.
+ * {@code equals} method; {@code false} otherwise
* @throws NullPointerException if the specified key is null
*/
@SuppressWarnings("unchecked")
@@ -974,13 +974,12 @@
}
/**
- * Returns <tt>true</tt> if this map maps one or more keys to the
- * specified value. Note: This method requires a full internal
- * traversal of the hash table, and so is much slower than
- * method <tt>containsKey</tt>.
+ * Returns {@code true} if this map maps one or more keys to the
+ * specified value. Note: This method requires a full traversal
+ * of the map, and so is much slower than method {@code containsKey}.
*
* @param value value whose presence in this map is to be tested
- * @return <tt>true</tt> if this map maps one or more keys to the
+ * @return {@code true} if this map maps one or more keys to the
* specified value
* @throws NullPointerException if the specified value is null
*/
@@ -1033,16 +1032,16 @@
/**
* Legacy method testing if some key maps into the specified value
* in this table. This method is identical in functionality to
- * {@link #containsValue}, and exists solely to ensure
+ * {@link #containsValue(Object)}, and exists solely to ensure
* full compatibility with class {@link java.util.Hashtable},
* which supported this method prior to introduction of the
* Java Collections framework.
*
* @param value a value to search for
- * @return <tt>true</tt> if and only if some key maps to the
- * <tt>value</tt> argument in this table as
- * determined by the <tt>equals</tt> method;
- * <tt>false</tt> otherwise
+ * @return {@code true} if and only if some key maps to the
+ * {@code value} argument in this table as
+ * determined by the {@code equals} method;
+ * {@code false} otherwise
* @throws NullPointerException if the specified value is null
*/
public boolean contains(Object value) {
@@ -1053,13 +1052,13 @@
* Maps the specified key to the specified value in this table.
* Neither the key nor the value can be null.
*
- * <p> The value can be retrieved by calling the <tt>get</tt> method
+ * <p>The value can be retrieved by calling the {@code get} method
* with a key that is equal to the original key.
*
* @param key key with which the specified value is to be associated
* @param value value to be associated with the specified key
- * @return the previous value associated with <tt>key</tt>, or
- * <tt>null</tt> if there was no mapping for <tt>key</tt>
+ * @return the previous value associated with {@code key}, or
+ * {@code null} if there was no mapping for {@code key}
* @throws NullPointerException if the specified key or value is null
*/
@SuppressWarnings("unchecked")
@@ -1079,7 +1078,7 @@
* {@inheritDoc}
*
* @return the previous value associated with the specified key,
- * or <tt>null</tt> if there was no mapping for the key
+ * or {@code null} if there was no mapping for the key
* @throws NullPointerException if the specified key or value is null
*/
@SuppressWarnings("unchecked")
@@ -1112,8 +1111,8 @@
* This method does nothing if the key is not in the map.
*
* @param key the key that needs to be removed
- * @return the previous value associated with <tt>key</tt>, or
- * <tt>null</tt> if there was no mapping for <tt>key</tt>
+ * @return the previous value associated with {@code key}, or
+ * {@code null} if there was no mapping for {@code key}
* @throws NullPointerException if the specified key is null
*/
public V remove(Object key) {
@@ -1151,7 +1150,7 @@
* {@inheritDoc}
*
* @return the previous value associated with the specified key,
- * or <tt>null</tt> if there was no mapping for the key
+ * or {@code null} if there was no mapping for the key
* @throws NullPointerException if the specified key or value is null
*/
public V replace(K key, V value) {
@@ -1177,14 +1176,14 @@
/**
* Returns a {@link Set} view of the keys contained in this map.
* The set is backed by the map, so changes to the map are
- * reflected in the set, and vice-versa. The set supports element
+ * reflected in the set, and vice-versa. The set supports element
* removal, which removes the corresponding mapping from this map,
- * via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
- * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
- * operations. It does not support the <tt>add</tt> or
- * <tt>addAll</tt> operations.
+ * via the {@code Iterator.remove}, {@code Set.remove},
+ * {@code removeAll}, {@code retainAll}, and {@code clear}
+ * operations. It does not support the {@code add} or
+ * {@code addAll} operations.
*
- * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
+ * <p>The view's {@code iterator} is a "weakly consistent" iterator
* that will never throw {@link ConcurrentModificationException},
* and guarantees to traverse elements as they existed upon
* construction of the iterator, and may (but is not guaranteed to)
@@ -1200,12 +1199,12 @@
* The collection is backed by the map, so changes to the map are
* reflected in the collection, and vice-versa. The collection
* supports element removal, which removes the corresponding
- * mapping from this map, via the <tt>Iterator.remove</tt>,
- * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
- * <tt>retainAll</tt>, and <tt>clear</tt> operations. It does not
- * support the <tt>add</tt> or <tt>addAll</tt> operations.
+ * mapping from this map, via the {@code Iterator.remove},
+ * {@code Collection.remove}, {@code removeAll},
+ * {@code retainAll}, and {@code clear} operations. It does not
+ * support the {@code add} or {@code addAll} operations.
*
- * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
+ * <p>The view's {@code iterator} is a "weakly consistent" iterator
* that will never throw {@link ConcurrentModificationException},
* and guarantees to traverse elements as they existed upon
* construction of the iterator, and may (but is not guaranteed to)
@@ -1221,12 +1220,12 @@
* The set is backed by the map, so changes to the map are
* reflected in the set, and vice-versa. The set supports element
* removal, which removes the corresponding mapping from the map,
- * via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
- * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
- * operations. It does not support the <tt>add</tt> or
- * <tt>addAll</tt> operations.
+ * via the {@code Iterator.remove}, {@code Set.remove},
+ * {@code removeAll}, {@code retainAll}, and {@code clear}
+ * operations. It does not support the {@code add} or
+ * {@code addAll} operations.
*
- * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
+ * <p>The view's {@code iterator} is a "weakly consistent" iterator
* that will never throw {@link ConcurrentModificationException},
* and guarantees to traverse elements as they existed upon
* construction of the iterator, and may (but is not guaranteed to)
@@ -1440,7 +1439,7 @@
/* ---------------- Serialization Support -------------- */
/**
- * Saves the state of the <tt>ConcurrentHashMap</tt> instance to a
+ * Saves the state of the {@code ConcurrentHashMap} instance to a
* stream (i.e., serializes it).
* @param s the stream
* @serialData
@@ -1477,8 +1476,7 @@
}
/**
- * Reconstitutes the <tt>ConcurrentHashMap</tt> instance from a
- * stream (i.e., deserializes it).
+ * Reconstitutes the instance from a stream (that is, deserializes it).
* @param s the stream
*/
@SuppressWarnings("unchecked")
--- a/jdk/src/share/classes/java/util/function/BiConsumer.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/BiConsumer.java Mon Jun 03 23:23:20 2013 -0700
@@ -24,14 +24,16 @@
*/
package java.util.function;
+import java.util.Objects;
+
/**
* An operation which accepts two input arguments and returns no result. This is
* the two-arity specialization of {@link Consumer}. Unlike most other
* functional interfaces, {@code BiConsumer} is expected to operate via
* side-effects.
*
- * @param <T> the type of the first argument to the {@code accept} operation.
- * @param <U> the type of the second argument to the {@code accept} operation.
+ * @param <T> the type of the first argument to the {@code accept} operation
+ * @param <U> the type of the second argument to the {@code accept} operation
*
* @see Consumer
* @since 1.8
@@ -47,4 +49,28 @@
* @param u an input object
*/
void accept(T t, U u);
+
+ /**
+ * Returns a {@code BiConsumer} which performs, in sequence, the operation
+ * represented by this object followed by the operation represented by
+ * the other {@code BiConsumer}.
+ *
+ * <p>Any exceptions thrown by either {@code accept} method are relayed
+ * to the caller; if performing this operation throws an exception, the
+ * other operation will not be performed.
+ *
+ * @param other a BiConsumer which will be chained after this BiConsumer
+ * @return a BiConsumer which performs in sequence the {@code accept} method
+ * of this BiConsumer and the {@code accept} method of the specified
+ * BiConsumer operation
+ * @throws NullPointerException if other is null
+ */
+ default BiConsumer<T, U> chain(BiConsumer<? super T, ? super U> other) {
+ Objects.requireNonNull(other);
+
+ return (l, r) -> {
+ accept(l, r);
+ other.accept(l, r);
+ };
+ }
}
--- a/jdk/src/share/classes/java/util/function/BiFunction.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/BiFunction.java Mon Jun 03 23:23:20 2013 -0700
@@ -24,15 +24,17 @@
*/
package java.util.function;
+import java.util.Objects;
+
/**
* Apply a function to the input arguments, yielding an appropriate result. This
* is the two-arity specialization of {@link Function}. A function may
* variously provide a mapping between types, object instances or keys and
* values or any other form of transformation upon the input.
*
- * @param <T> the type of the first argument to the {@code apply} operation.
- * @param <U> the type of the second argument to the {@code apply} operation.
- * @param <R> the type of results returned by the {@code apply} operation.
+ * @param <T> the type of the first argument to the {@code apply} operation
+ * @param <U> the type of the second argument to the {@code apply} operation
+ * @param <R> the type of results returned by the {@code apply} operation
*
* @see Function
* @since 1.8
@@ -48,4 +50,22 @@
* @return the function result
*/
R apply(T t, U u);
+
+ /**
+ * Returns a new function which applies this function followed by the
+ * provided function. If either function throws an exception, it is relayed
+ * to the caller.
+ *
+ * @param <V> Type of output objects to the combined function. May be the
+ * same type as {@code <T>}, {@code <U>} or {@code <R>}
+ * @param after An additional function to be applied after this function is
+ * applied
+ * @return A function which performs this function followed by the provided
+ * function
+ * @throws NullPointerException if after is null
+ */
+ default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
+ Objects.requireNonNull(after);
+ return (T t, U u) -> after.apply(apply(t, u));
+ }
}
--- a/jdk/src/share/classes/java/util/function/BiPredicate.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/BiPredicate.java Mon Jun 03 23:23:20 2013 -0700
@@ -30,8 +30,8 @@
* Determines if the input objects match some criteria. This is the two-arity
* specialization of {@link Predicate}.
*
- * @param <T> the type of the first argument to {@code test}.
- * @param <U> the type of the second argument to {@code test}.
+ * @param <T> the type of the first argument to {@code test}
+ * @param <U> the type of the second argument to {@code test}
*
* @see Predicate
* @since 1.8
@@ -42,9 +42,9 @@
/**
* Return {@code true} if the inputs match some criteria.
*
- * @param t an input object.
- * @param u an input object.
- * @return {@code true} if the inputs match some criteria.
+ * @param t an input object
+ * @param u an input object
+ * @return {@code true} if the inputs match some criteria
*/
boolean test(T t, U u);
@@ -54,11 +54,12 @@
* this predicate returns {@code false} then the remaining predicate is not
* evaluated.
*
- * @param p a predicate which will be logically-ANDed with this predicate.
+ * @param p a predicate which will be logically-ANDed with this predicate
* @return a new predicate which returns {@code true} only if both
- * predicates return {@code true}.
+ * predicates return {@code true}
+ * @throws NullPointerException if p is null
*/
- public default BiPredicate<T, U> and(BiPredicate<? super T, ? super U> p) {
+ default BiPredicate<T, U> and(BiPredicate<? super T, ? super U> p) {
Objects.requireNonNull(p);
return (T t, U u) -> test(t, u) && p.test(t, u);
}
@@ -67,9 +68,9 @@
* Returns a predicate which negates the result of this predicate.
*
* @return a new predicate who's result is always the opposite of this
- * predicate.
+ * predicate
*/
- public default BiPredicate<T, U> negate() {
+ default BiPredicate<T, U> negate() {
return (T t, U u) -> !test(t, u);
}
@@ -79,25 +80,13 @@
* predicate returns {@code true} then the remaining predicate is not
* evaluated.
*
- * @param p a predicate which will be logically-ORed with this predicate.
+ * @param p a predicate which will be logically-ORed with this predicate
* @return a new predicate which returns {@code true} if either predicate
- * returns {@code true}.
+ * returns {@code true}
+ * @throws NullPointerException if p is null
*/
- public default BiPredicate<T, U> or(BiPredicate<? super T, ? super U> p) {
+ default BiPredicate<T, U> or(BiPredicate<? super T, ? super U> p) {
Objects.requireNonNull(p);
return (T t, U u) -> test(t, u) || p.test(t, u);
}
-
- /**
- * Returns a predicate that evaluates to {@code true} if both or neither of
- * the component predicates evaluate to {@code true}.
- *
- * @param p a predicate which will be logically-XORed with this predicate.
- * @return a predicate that evaluates to {@code true} if both or neither of
- * the component predicates evaluate to {@code true}.
- */
- public default BiPredicate<T, U> xor(BiPredicate<? super T, ? super U> p) {
- Objects.requireNonNull(p);
- return (T t, U u) -> test(t, u) ^ p.test(t, u);
- }
}
--- a/jdk/src/share/classes/java/util/function/BooleanSupplier.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/BooleanSupplier.java Mon Jun 03 23:23:20 2013 -0700
@@ -40,5 +40,5 @@
*
* @return a {@code boolean} value
*/
- public boolean getAsBoolean();
+ boolean getAsBoolean();
}
--- a/jdk/src/share/classes/java/util/function/Consumer.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/Consumer.java Mon Jun 03 23:23:20 2013 -0700
@@ -24,6 +24,8 @@
*/
package java.util.function;
+import java.util.Objects;
+
/**
* An operation which accepts a single input argument and returns no result.
* Unlike most other functional interfaces, {@code Consumer} is expected to
@@ -41,5 +43,25 @@
*
* @param t the input object
*/
- public void accept(T t);
+ void accept(T t);
+
+ /**
+ * Returns a {@code Consumer} which performs, in sequence, the operation
+ * represented by this object followed by the operation represented by
+ * the other {@code Consumer}.
+ *
+ * <p>Any exceptions thrown by either {@code accept} method are relayed
+ * to the caller; if performing this operation throws an exception, the
+ * other operation will not be performed.
+ *
+ * @param other a Consumer which will be chained after this Consumer
+ * @return a Consumer which performs in sequence the {@code accept} method
+ * of this Consumer and the {@code accept} method of the specified Consumer
+ * operation
+ * @throws NullPointerException if other is null
+ */
+ default Consumer<T> chain(Consumer<? super T> other) {
+ Objects.requireNonNull(other);
+ return (T t) -> { accept(t); other.accept(t); };
+ }
}
--- a/jdk/src/share/classes/java/util/function/DoubleBinaryOperator.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/DoubleBinaryOperator.java Mon Jun 03 23:23:20 2013 -0700
@@ -43,5 +43,5 @@
* @param right the right operand value
* @return the result of the operation
*/
- public double applyAsDouble(double left, double right);
+ double applyAsDouble(double left, double right);
}
--- a/jdk/src/share/classes/java/util/function/DoubleConsumer.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/DoubleConsumer.java Mon Jun 03 23:23:20 2013 -0700
@@ -24,6 +24,8 @@
*/
package java.util.function;
+import java.util.Objects;
+
/**
* An operation which accepts a single double argument and returns no result.
* This is the primitive type specialization of {@link Consumer} for
@@ -41,5 +43,26 @@
*
* @param value the input value
*/
- public void accept(double value);
+ void accept(double value);
+
+ /**
+ * Returns a {@code DoubleConsumer} which performs, in sequence, the operation
+ * represented by this object followed by the operation represented by
+ * another {@code DoubleConsumer}.
+ *
+ * <p>Any exceptions thrown by either {@code accept} method are relayed
+ * to the caller; if performing this operation throws an exception, the
+ * other operation will not be performed.
+ *
+ * @param other a DoubleConsumer which will be chained after this
+ * DoubleConsumer
+ * @return an DoubleConsumer which performs in sequence the {@code accept} method
+ * of this DoubleConsumer and the {@code accept} method of the specified IntConsumer
+ * operation
+ * @throws NullPointerException if other is null
+ */
+ default DoubleConsumer chain(DoubleConsumer other) {
+ Objects.requireNonNull(other);
+ return (double t) -> { accept(t); other.accept(t); };
+ }
}
--- a/jdk/src/share/classes/java/util/function/DoubleFunction.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/DoubleFunction.java Mon Jun 03 23:23:20 2013 -0700
@@ -43,5 +43,5 @@
* @param value the input value
* @return the function result
*/
- public R apply(double value);
+ R apply(double value);
}
--- a/jdk/src/share/classes/java/util/function/DoublePredicate.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/DoublePredicate.java Mon Jun 03 23:23:20 2013 -0700
@@ -40,11 +40,11 @@
/**
* Returns {@code true} if the input value matches some criteria.
*
- * @param value the value to be tested.
+ * @param value the value to be tested
* @return {@code true} if the input value matches some criteria, otherwise
- * {@code false}.
+ * {@code false}
*/
- public boolean test(double value);
+ boolean test(double value);
/**
* Returns a predicate which evaluates to {@code true} only if this
@@ -52,11 +52,16 @@
* this predicate returns {@code false} then the remaining predicate is not
* evaluated.
*
- * @param p a predicate which will be logically-ANDed with this predicate.
+ * <p>Any exceptions thrown by either {@code test} method are relayed
+ * to the caller; if performing first operation throws an exception, the
+ * second operation will not be performed.
+ *
+ * @param p a predicate which will be logically-ANDed with this predicate
* @return a new predicate which returns {@code true} only if both
- * predicates return {@code true}.
+ * predicates return {@code true}
+ * @throws NullPointerException if p is null
*/
- public default DoublePredicate and(DoublePredicate p) {
+ default DoublePredicate and(DoublePredicate p) {
Objects.requireNonNull(p);
return (value) -> test(value) && p.test(value);
}
@@ -65,9 +70,9 @@
* Returns a predicate which negates the result of this predicate.
*
* @return a new predicate who's result is always the opposite of this
- * predicate.
+ * predicate
*/
- public default DoublePredicate negate() {
+ default DoublePredicate negate() {
return (value) -> !test(value);
}
@@ -77,25 +82,17 @@
* predicate returns {@code true} then the remaining predicate is not
* evaluated.
*
- * @param p a predicate which will be logically-ANDed with this predicate.
+ * <p>Any exceptions thrown by either {@code test} method are relayed
+ * to the caller; if performing first operation throws an exception, the
+ * second operation will not be performed.
+ *
+ * @param p a predicate which will be logically-ANDed with this predicate
* @return a new predicate which returns {@code true} if either predicate
- * returns {@code true}.
+ * returns {@code true}
+ * @throws NullPointerException if p is null
*/
- public default DoublePredicate or(DoublePredicate p) {
+ default DoublePredicate or(DoublePredicate p) {
Objects.requireNonNull(p);
return (value) -> test(value) || p.test(value);
}
-
- /**
- * Returns a predicate that evaluates to {@code true} if both or neither of
- * the component predicates evaluate to {@code true}.
- *
- * @param p a predicate which will be logically-XORed with this predicate.
- * @return a predicate that evaluates to {@code true} if all or none of the
- * component predicates evaluate to {@code true}.
- */
- public default DoublePredicate xor(DoublePredicate p) {
- Objects.requireNonNull(p);
- return (value) -> test(value) ^ p.test(value);
- }
}
--- a/jdk/src/share/classes/java/util/function/DoubleSupplier.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/DoubleSupplier.java Mon Jun 03 23:23:20 2013 -0700
@@ -39,5 +39,5 @@
*
* @return a {@code double} value
*/
- public double getAsDouble();
+ double getAsDouble();
}
--- a/jdk/src/share/classes/java/util/function/DoubleUnaryOperator.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/DoubleUnaryOperator.java Mon Jun 03 23:23:20 2013 -0700
@@ -24,6 +24,8 @@
*/
package java.util.function;
+import java.util.Objects;
+
/**
* An operation on a {@code double} operand yielding a {@code double}
* result. This is the primitive type specialization of {@link UnaryOperator}
@@ -42,5 +44,46 @@
* @param operand the operand value
* @return the operation result value
*/
- public double applyAsDouble(double operand);
+ double applyAsDouble(double operand);
+
+ /**
+ * Compose a new function which applies the provided function followed by
+ * this function. If either function throws an exception, it is relayed
+ * to the caller.
+ *
+ * @param before An additional function to be applied before this function
+ * is applied
+ * @return A function which performs the provided function followed by this
+ * function
+ * @throws NullPointerException if before is null
+ */
+ default DoubleUnaryOperator compose(DoubleUnaryOperator before) {
+ Objects.requireNonNull(before);
+ return (double v) -> applyAsDouble(before.applyAsDouble(v));
+ }
+
+ /**
+ * Compose a new function which applies this function followed by the
+ * provided function. If either function throws an exception, it is relayed
+ * to the caller.
+ *
+ * @param after An additional function to be applied after this function is
+ * applied
+ * @return A function which performs this function followed by the provided
+ * function followed
+ * @throws NullPointerException if after is null
+ */
+ default DoubleUnaryOperator andThen(DoubleUnaryOperator after) {
+ Objects.requireNonNull(after);
+ return (double t) -> after.applyAsDouble(applyAsDouble(t));
+ }
+
+ /**
+ * Returns a unary operator that provides its input value as the result.
+ *
+ * @return a unary operator that provides its input value as the result
+ */
+ static DoubleUnaryOperator identity() {
+ return t -> t;
+ }
}
--- a/jdk/src/share/classes/java/util/function/Function.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/Function.java Mon Jun 03 23:23:20 2013 -0700
@@ -24,14 +24,15 @@
*/
package java.util.function;
+import java.util.Objects;
/**
* Apply a function to the input argument, yielding an appropriate result. A
* function may variously provide a mapping between types, object instances or
* keys and values or any other form of transformation upon the input.
*
- * @param <T> the type of the input to the {@code apply} operation.
- * @param <R> the type of the result of the {@code apply} operation.
+ * @param <T> the type of the input to the {@code apply} operation
+ * @param <R> the type of the result of the {@code apply} operation
*
* @since 1.8
*/
@@ -44,5 +45,50 @@
* @param t the input object
* @return the function result
*/
- public R apply(T t);
+ R apply(T t);
+
+ /**
+ * Returns a new function which applies the provided function followed by
+ * this function. If either function throws an exception, it is relayed
+ * to the caller.
+ *
+ * @param <V> type of input objects to the combined function. May be the
+ * same type as {@code <T>} or {@code <R>}
+ * @param before an additional function to be applied before this function
+ * is applied
+ * @return a function which performs the provided function followed by this
+ * function
+ * @throws NullPointerException if before is null
+ */
+ default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
+ Objects.requireNonNull(before);
+ return (V v) -> apply(before.apply(v));
+ }
+
+ /**
+ * Returns a new function which applies this function followed by the
+ * provided function. If either function throws an exception, it is relayed
+ * to the caller.
+ *
+ * @param <V> type of output objects to the combined function. May be the
+ * same type as {@code <T>} or {@code <R>}
+ * @param after an additional function to be applied after this function is
+ * applied
+ * @return a function which performs this function followed by the provided
+ * function
+ * @throws NullPointerException if after is null
+ */
+ default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
+ Objects.requireNonNull(after);
+ return (T t) -> after.apply(apply(t));
+ }
+
+ /**
+ * Returns a {@code Function} whose {@code apply} method returns its input.
+ *
+ * @param <T> the type of the input and output objects to the function
+ */
+ static <T> Function<T, T> identity() {
+ return t -> t;
+ }
}
--- a/jdk/src/share/classes/java/util/function/IntBinaryOperator.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/IntBinaryOperator.java Mon Jun 03 23:23:20 2013 -0700
@@ -44,5 +44,5 @@
* @param right the right operand value
* @return the result of the operation
*/
- public int applyAsInt(int left, int right);
+ int applyAsInt(int left, int right);
}
--- a/jdk/src/share/classes/java/util/function/IntConsumer.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/IntConsumer.java Mon Jun 03 23:23:20 2013 -0700
@@ -24,6 +24,8 @@
*/
package java.util.function;
+import java.util.Objects;
+
/**
* An operation which accepts a single integer argument and returns no result.
* This is the primitive type specialization of {@link Consumer} for {@code int}.
@@ -41,5 +43,26 @@
*
* @param value the input value
*/
- public void accept(int value);
+ void accept(int value);
+
+ /**
+ * Returns an {@code IntConsumer} which performs, in sequence, the operation
+ * represented by this object followed by the operation represented by
+ * another {@code IntConsumer}.
+ *
+ * <p>Any exceptions thrown by either {@code accept} method are relayed
+ * to the caller; if performing this operation throws an exception, the
+ * other operation will not be performed.
+ *
+ * @param other an IntConsumer which will be chained after this
+ * IntConsumer
+ * @return an IntConsumer which performs in sequence the {@code accept} method
+ * of this IntConsumer and the {@code accept} method of the specified IntConsumer
+ * operation
+ * @throws NullPointerException if other is null
+ */
+ default IntConsumer chain(IntConsumer other) {
+ Objects.requireNonNull(other);
+ return (int t) -> { accept(t); other.accept(t); };
+ }
}
--- a/jdk/src/share/classes/java/util/function/IntFunction.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/IntFunction.java Mon Jun 03 23:23:20 2013 -0700
@@ -43,5 +43,5 @@
* @param value the input value
* @return the function result
*/
- public R apply(int value);
+ R apply(int value);
}
--- a/jdk/src/share/classes/java/util/function/IntPredicate.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/IntPredicate.java Mon Jun 03 23:23:20 2013 -0700
@@ -39,11 +39,11 @@
/**
* Returns {@code true} if the input value matches some criteria.
*
- * @param value the value to be tested.
+ * @param value the value to be tested
* @return {@code true} if the input value matches some criteria, otherwise
* {@code false}
*/
- public boolean test(int value);
+ boolean test(int value);
/**
* Returns a predicate which evaluates to {@code true} only if this
@@ -51,11 +51,16 @@
* this predicate returns {@code false} then the remaining predicate is not
* evaluated.
*
- * @param p a predicate which will be logically-ANDed with this predicate.
+ * <p>Any exceptions thrown by either {@code test} method are relayed
+ * to the caller; if performing first operation throws an exception, the
+ * second operation will not be performed.
+ *
+ * @param p a predicate which will be logically-ANDed with this predicate
* @return a new predicate which returns {@code true} only if both
- * predicates return {@code true}.
+ * predicates return {@code true}
+ * @throws NullPointerException if p is null
*/
- public default IntPredicate and(IntPredicate p) {
+ default IntPredicate and(IntPredicate p) {
Objects.requireNonNull(p);
return (value) -> test(value) && p.test(value);
}
@@ -64,9 +69,9 @@
* Returns a predicate which negates the result of this predicate.
*
* @return a new predicate who's result is always the opposite of this
- * predicate.
+ * predicate
*/
- public default IntPredicate negate() {
+ default IntPredicate negate() {
return (value) -> !test(value);
}
@@ -76,25 +81,17 @@
* predicate returns {@code true} then the remaining predicate is not
* evaluated.
*
- * @param p a predicate which will be logically-ORed with this predicate.
+ * <p>Any exceptions thrown by either {@code test} method are relayed
+ * to the caller; if performing first operation throws an exception, the
+ * second operation will not be performed.
+ *
+ * @param p a predicate which will be logically-ORed with this predicate
* @return a new predicate which returns {@code true} if either predicate
- * returns {@code true}.
+ * returns {@code true}
+ * @throws NullPointerException if p is null
*/
- public default IntPredicate or(IntPredicate p) {
+ default IntPredicate or(IntPredicate p) {
Objects.requireNonNull(p);
return (value) -> test(value) || p.test(value);
}
-
- /**
- * Returns a predicate that evaluates to {@code true} if both or neither of
- * the component predicates evaluate to {@code true}.
- *
- * @param p a predicate which will be logically-XORed with this predicate.
- * @return a predicate that evaluates to {@code true} if both or neither of
- * the component predicates evaluate to {@code true}
- */
- public default IntPredicate xor(IntPredicate p) {
- Objects.requireNonNull(p);
- return (value) -> test(value) ^ p.test(value);
- }
}
--- a/jdk/src/share/classes/java/util/function/IntSupplier.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/IntSupplier.java Mon Jun 03 23:23:20 2013 -0700
@@ -39,5 +39,5 @@
*
* @return an {@code int} value
*/
- public int getAsInt();
+ int getAsInt();
}
--- a/jdk/src/share/classes/java/util/function/IntUnaryOperator.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/IntUnaryOperator.java Mon Jun 03 23:23:20 2013 -0700
@@ -24,6 +24,8 @@
*/
package java.util.function;
+import java.util.Objects;
+
/**
* An operation on a single {@code int} operand yielding an {@code int} result.
* This is the primitive type specialization of {@link UnaryOperator} for
@@ -37,10 +39,51 @@
/**
* Returns the {@code int} value result of the operation upon the
- * {@code int} operand.
+ * {@code int} operand.
*
* @param operand the operand value
* @return the operation result value
*/
- public int applyAsInt(int operand);
+ int applyAsInt(int operand);
+
+ /**
+ * Compose a new function which applies the provided function followed by
+ * this function. If either function throws an exception, it is relayed
+ * to the caller.
+ *
+ * @param before an additional function to be applied before this function
+ * is applied
+ * @return a function which performs the provided function followed by this
+ * function
+ * @throws NullPointerException if before is null
+ */
+ default IntUnaryOperator compose(IntUnaryOperator before) {
+ Objects.requireNonNull(before);
+ return (int v) -> applyAsInt(before.applyAsInt(v));
+ }
+
+ /**
+ * Compose a new function which applies this function followed by the
+ * provided function. If either function throws an exception, it is relayed
+ * to the caller.
+ *
+ * @param after an additional function to be applied after this function is
+ * applied
+ * @return a function which performs this function followed by the provided
+ * function followed
+ * @throws NullPointerException if after is null
+ */
+ default IntUnaryOperator andThen(IntUnaryOperator after) {
+ Objects.requireNonNull(after);
+ return (int t) -> after.applyAsInt(applyAsInt(t));
+ }
+
+ /**
+ * Returns a unary operator that provides its input value as the result.
+ *
+ * @return a unary operator that provides its input value as the result
+ */
+ static IntUnaryOperator identity() {
+ return t -> t;
+ }
}
--- a/jdk/src/share/classes/java/util/function/LongBinaryOperator.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/LongBinaryOperator.java Mon Jun 03 23:23:20 2013 -0700
@@ -44,5 +44,5 @@
* @param right the right operand value
* @return the result of the operation
*/
- public long applyAsLong(long left, long right);
+ long applyAsLong(long left, long right);
}
--- a/jdk/src/share/classes/java/util/function/LongConsumer.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/LongConsumer.java Mon Jun 03 23:23:20 2013 -0700
@@ -24,6 +24,8 @@
*/
package java.util.function;
+import java.util.Objects;
+
/**
* An operation which accepts a single long argument and returns no result.
* This is the {@code long}-consuming primitive type specialization of
@@ -41,5 +43,26 @@
*
* @param value the input value
*/
- public void accept(long value);
+ void accept(long value);
+
+ /**
+ * Returns a {@code LongConsumer} which performs, in sequence, the operation
+ * represented by this object followed by the operation represented by
+ * another {@code LongConsumer}.
+ *
+ * <p>Any exceptions thrown by either {@code accept} method are relayed
+ * to the caller; if performing this operation throws an exception, the
+ * other operation will not be performed.
+ *
+ * @param other a LongConsumer which will be chained after this
+ * LongConsumer
+ * @return a LongConsumer which performs in sequence the {@code accept} method
+ * of this LongConsumer and the {@code accept} method of the specified LongConsumer
+ * operation
+ * @throws NullPointerException if other is null
+ */
+ default LongConsumer chain(LongConsumer other) {
+ Objects.requireNonNull(other);
+ return (long t) -> { accept(t); other.accept(t); };
+ }
}
--- a/jdk/src/share/classes/java/util/function/LongFunction.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/LongFunction.java Mon Jun 03 23:23:20 2013 -0700
@@ -43,5 +43,5 @@
* @param value the input value
* @return the function result
*/
- public R apply(long value);
+ R apply(long value);
}
--- a/jdk/src/share/classes/java/util/function/LongPredicate.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/LongPredicate.java Mon Jun 03 23:23:20 2013 -0700
@@ -39,11 +39,11 @@
/**
* Returns {@code true} if the input value matches some criteria.
*
- * @param value the value to be tested.
+ * @param value the value to be tested
* @return {@code true} if the input value matches some criteria, otherwise
- * {@code false}.
+ * {@code false}
*/
- public boolean test(long value);
+ boolean test(long value);
/**
* Returns a predicate which evaluates to {@code true} only if this
@@ -51,11 +51,15 @@
* this predicate returns {@code false} then the remaining predicate is not
* evaluated.
*
- * @param p a predicate which will be logically-ANDed with this predicate.
+ * <p>Any exceptions thrown by either {@code test} method are relayed
+ * to the caller; if performing first operation throws an exception, the
+ * second operation will not be performed.
+ *
+ * @param p a predicate which will be logically-ANDed with this predicate
* @return a new predicate which returns {@code true} only if both
- * predicates return {@code true}.
+ * predicates return {@code true}
*/
- public default LongPredicate and(LongPredicate p) {
+ default LongPredicate and(LongPredicate p) {
Objects.requireNonNull(p);
return (value) -> test(value) && p.test(value);
}
@@ -64,9 +68,9 @@
* Returns a predicate which negates the result of this predicate.
*
* @return a new predicate who's result is always the opposite of this
- * predicate.
+ * predicate
*/
- public default LongPredicate negate() {
+ default LongPredicate negate() {
return (value) -> !test(value);
}
@@ -76,25 +80,17 @@
* predicate returns {@code true} then the remaining predicate is not
* evaluated.
*
- * @param p a predicate which will be logically-ORed with this predicate.
+ * <p>Any exceptions thrown by either {@code test} method are relayed
+ * to the caller; if performing first operation throws an exception, the
+ * second operation will not be performed.
+ *
+ * @param p a predicate which will be logically-ORed with this predicate
* @return a new predicate which returns {@code true} if either predicate
- * returns {@code true}.
+ * returns {@code true}
+ * @throws NullPointerException if p is null
*/
- public default LongPredicate or(LongPredicate p) {
+ default LongPredicate or(LongPredicate p) {
Objects.requireNonNull(p);
return (value) -> test(value) || p.test(value);
}
-
- /**
- * Returns a predicate that evaluates to {@code true} if both or neither of
- * the component predicates evaluate to {@code true}.
- *
- * @param p a predicate which will be logically-XORed with this predicate.
- * @return a predicate that evaluates to {@code true} if both or neither of
- * the component predicates evaluate to {@code true}.
- */
- public default LongPredicate xor(LongPredicate p) {
- Objects.requireNonNull(p);
- return (value) -> test(value) ^ p.test(value);
- }
}
--- a/jdk/src/share/classes/java/util/function/LongSupplier.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/LongSupplier.java Mon Jun 03 23:23:20 2013 -0700
@@ -39,5 +39,5 @@
*
* @return a {@code long} value
*/
- public long getAsLong();
+ long getAsLong();
}
--- a/jdk/src/share/classes/java/util/function/LongUnaryOperator.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/LongUnaryOperator.java Mon Jun 03 23:23:20 2013 -0700
@@ -24,6 +24,8 @@
*/
package java.util.function;
+import java.util.Objects;
+
/**
* An operation on a single {@code long} operand yielding a {@code long} result.
* This is the primitive type specialization of {@link UnaryOperator} for
@@ -42,5 +44,46 @@
* @param operand the operand value
* @return the operation result value
*/
- public long applyAsLong(long operand);
+ long applyAsLong(long operand);
+
+ /**
+ * Compose a new function which applies the provided function followed by
+ * this function. If either function throws an exception, it is relayed
+ * to the caller.
+ *
+ * @param before An additional function to be applied before this function
+ * is applied
+ * @return A function which performs the provided function followed by this
+ * function
+ * @throws NullPointerException if before is null
+ */
+ default LongUnaryOperator compose(LongUnaryOperator before) {
+ Objects.requireNonNull(before);
+ return (long v) -> applyAsLong(before.applyAsLong(v));
+ }
+
+ /**
+ * Compose a new function which applies this function followed by the
+ * provided function. If either function throws an exception, it is relayed
+ * to the caller.
+ *
+ * @param after An additional function to be applied after this function is
+ * applied
+ * @return A function which performs this function followed by the provided
+ * function followed
+ * @throws NullPointerException if after is null
+ */
+ default LongUnaryOperator andThen(LongUnaryOperator after) {
+ Objects.requireNonNull(after);
+ return (long t) -> after.applyAsLong(applyAsLong(t));
+ }
+
+ /**
+ * Returns a unary operator that provides its input value as the result.
+ *
+ * @return a unary operator that provides its input value as the result
+ */
+ static LongUnaryOperator identity() {
+ return t -> t;
+ }
}
--- a/jdk/src/share/classes/java/util/function/ObjDoubleConsumer.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/ObjDoubleConsumer.java Mon Jun 03 23:23:20 2013 -0700
@@ -44,5 +44,5 @@
* @param t an input object
* @param value an input value
*/
- public void accept(T t, double value);
+ void accept(T t, double value);
}
--- a/jdk/src/share/classes/java/util/function/ObjIntConsumer.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/ObjIntConsumer.java Mon Jun 03 23:23:20 2013 -0700
@@ -30,7 +30,7 @@
* {@link BiConsumer}. Unlike most other functional interfaces,
* {@code ObjIntConsumer} is expected to operate via side-effects.
*
- * @param <T> Type of reference argument to {@code accept()}.
+ * @param <T> Type of reference argument to {@code accept()}
*
* @see BiConsumer
* @since 1.8
@@ -44,5 +44,5 @@
* @param t an input object
* @param value an input value
*/
- public void accept(T t, int value);
+ void accept(T t, int value);
}
--- a/jdk/src/share/classes/java/util/function/ObjLongConsumer.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/ObjLongConsumer.java Mon Jun 03 23:23:20 2013 -0700
@@ -30,7 +30,7 @@
* {@link BiConsumer}. Unlike most other functional interfaces,
* {@code ObjLongConsumer} is expected to operate via side-effects.
*
- * @param <T> Type of reference argument to {@code accept()}.
+ * @param <T> Type of reference argument to {@code accept()}
*
* @see BiConsumer
* @since 1.8
@@ -44,5 +44,5 @@
* @param t an input object
* @param value an input value
*/
- public void accept(T t, long value);
+ void accept(T t, long value);
}
--- a/jdk/src/share/classes/java/util/function/Predicate.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/Predicate.java Mon Jun 03 23:23:20 2013 -0700
@@ -43,7 +43,7 @@
* @return {@code true} if the input object matches some criteria, otherwise
* {@code false}
*/
- public boolean test(T t);
+ boolean test(T t);
/**
* Returns a predicate which evaluates to {@code true} only if this
@@ -51,11 +51,16 @@
* this predicate returns {@code false} then the remaining predicate is not
* evaluated.
*
- * @param p a predicate which will be logically-ANDed with this predicate.
+ * <p>Any exceptions thrown by either {@code test} method are relayed
+ * to the caller; if performing first operation throws an exception, the
+ * second operation will not be performed.
+ *
+ * @param p a predicate which will be logically-ANDed with this predicate
* @return a new predicate which returns {@code true} only if both
- * predicates return {@code true}.
+ * predicates return {@code true}
+ * @throws NullPointerException if p is null
*/
- public default Predicate<T> and(Predicate<? super T> p) {
+ default Predicate<T> and(Predicate<? super T> p) {
Objects.requireNonNull(p);
return (t) -> test(t) && p.test(t);
}
@@ -66,7 +71,7 @@
* @return a new predicate who's result is always the opposite of this
* predicate.
*/
- public default Predicate<T> negate() {
+ default Predicate<T> negate() {
return (t) -> !test(t);
}
@@ -76,25 +81,32 @@
* predicate returns {@code true} then the remaining predicate is not
* evaluated.
*
- * @param p a predicate which will be logically-ORed with this predicate.
+ * <p>Any exceptions thrown by either {@code test} method are relayed
+ * to the caller; if performing first operation throws an exception, the
+ * second operation will not be performed.
+ *
+ * @param p a predicate which will be logically-ORed with this predicate
* @return a new predicate which returns {@code true} if either predicate
- * returns {@code true}.
+ * returns {@code true}
+ * @throws NullPointerException if p is null
*/
- public default Predicate<T> or(Predicate<? super T> p) {
+ default Predicate<T> or(Predicate<? super T> p) {
Objects.requireNonNull(p);
return (t) -> test(t) || p.test(t);
}
/**
- * Returns a predicate that evaluates to {@code true} if both or neither of
- * the component predicates evaluate to {@code true}.
+ * Returns a predicate who's result matches
+ * {@code Objects.equals(target, t)}.
*
- * @param p a predicate which will be logically-XORed with this predicte.
- * @return a predicate that evaluates to {@code true} if both or neither of
- * the component predicates evaluate to {@code true}.
+ * @param <T> the type of values evaluated by the predicate
+ * @param target the target value to be compared for equality
+ * @return a predicate who's result matches
+ * {@code Objects.equals(target, t)}
*/
- public default Predicate<T> xor(Predicate<? super T> p) {
- Objects.requireNonNull(p);
- return (t) -> test(t) ^ p.test(t);
+ static <T> Predicate<T> isEqual(Object target) {
+ return (null == target)
+ ? Objects::isNull
+ : object -> target.equals(object);
}
}
--- a/jdk/src/share/classes/java/util/function/Supplier.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/Supplier.java Mon Jun 03 23:23:20 2013 -0700
@@ -40,5 +40,5 @@
*
* @return an object
*/
- public T get();
+ T get();
}
--- a/jdk/src/share/classes/java/util/function/ToDoubleBiFunction.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/ToDoubleBiFunction.java Mon Jun 03 23:23:20 2013 -0700
@@ -46,5 +46,5 @@
* @param u an input object
* @return the function result value
*/
- public double applyAsDouble(T t, U u);
+ double applyAsDouble(T t, U u);
}
--- a/jdk/src/share/classes/java/util/function/ToDoubleFunction.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/ToDoubleFunction.java Mon Jun 03 23:23:20 2013 -0700
@@ -42,5 +42,5 @@
* @param t the input object
* @return the function result value
*/
- public double applyAsDouble(T t);
+ double applyAsDouble(T t);
}
--- a/jdk/src/share/classes/java/util/function/ToIntBiFunction.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/ToIntBiFunction.java Mon Jun 03 23:23:20 2013 -0700
@@ -28,10 +28,10 @@
* Apply a function to the input arguments, yielding an appropriate result.
* This is the {@code int}-bearing specialization for {@link BiFunction}.
*
- * @param <T> the type of the first argument to the {@code applyAsLong}
- * operation.
- * @param <U> the type of the second argument to the {@code applyAsLong}
- * operation.
+ * @param <T> the type of the first argument to the {@code applyAsInt}
+ * operation
+ * @param <U> the type of the second argument to the {@code applyAsInt}
+ * operation
*
* @see BiFunction
* @since 1.8
@@ -46,5 +46,5 @@
* @param u an input object
* @return the function result value
*/
- public int applyAsInt(T t, U u);
+ int applyAsInt(T t, U u);
}
--- a/jdk/src/share/classes/java/util/function/ToIntFunction.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/ToIntFunction.java Mon Jun 03 23:23:20 2013 -0700
@@ -42,5 +42,5 @@
* @param t the input object
* @return the function result value
*/
- public int applyAsInt(T t);
+ int applyAsInt(T t);
}
--- a/jdk/src/share/classes/java/util/function/ToLongBiFunction.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/ToLongBiFunction.java Mon Jun 03 23:23:20 2013 -0700
@@ -46,5 +46,5 @@
* @param u an input object
* @return the function result value
*/
- public long applyAsLong(T t, U u);
+ long applyAsLong(T t, U u);
}
--- a/jdk/src/share/classes/java/util/function/ToLongFunction.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/ToLongFunction.java Mon Jun 03 23:23:20 2013 -0700
@@ -42,5 +42,5 @@
* @param t the input object
* @return the function result value
*/
- public long applyAsLong(T t);
+ long applyAsLong(T t);
}
--- a/jdk/src/share/classes/java/util/function/UnaryOperator.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/java/util/function/UnaryOperator.java Mon Jun 03 23:23:20 2013 -0700
@@ -36,4 +36,13 @@
*/
@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {
+
+ /**
+ * Returns a unary operator that provides its input value as the result.
+ *
+ * @return a unary operator that provides its input value as the result
+ */
+ static <T> UnaryOperator<T> identity() {
+ return t -> t;
+ }
}
--- a/jdk/src/share/classes/javax/swing/JToolTip.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/javax/swing/JToolTip.java Mon Jun 03 23:23:20 2013 -0700
@@ -31,6 +31,7 @@
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
+import java.util.Objects;
/**
@@ -128,6 +129,11 @@
String oldValue = this.tipText;
this.tipText = tipText;
firePropertyChange("tiptext", oldValue, tipText);
+
+ if (!Objects.equals(oldValue, tipText)) {
+ revalidate();
+ repaint();
+ }
}
/**
--- a/jdk/src/share/classes/javax/swing/text/View.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/javax/swing/text/View.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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
@@ -1174,6 +1174,7 @@
// formed by added elements (i.e. they will be updated
// by initialization.
index0 = Math.max(index0, 0);
+ index1 = getViewIndex(elem.getDocument().getLength(), Position.Bias.Forward);
for (int i = index0; i <= index1; i++) {
if (! ((i >= hole0) && (i <= hole1))) {
v = getView(i);
--- a/jdk/src/share/classes/javax/swing/text/html/parser/Parser.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/javax/swing/text/html/parser/Parser.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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
@@ -1980,11 +1980,12 @@
void parseScript() throws IOException {
char[] charsToAdd = new char[SCRIPT_END_TAG.length];
+ boolean insideComment = false;
/* Here, ch should be the first character after <script> */
while (true) {
int i = 0;
- while (i < SCRIPT_END_TAG.length
+ while (!insideComment && i < SCRIPT_END_TAG.length
&& (SCRIPT_END_TAG[i] == ch
|| SCRIPT_END_TAG_UPPER_CASE[i] == ch)) {
charsToAdd[i] = (char) ch;
@@ -2025,6 +2026,13 @@
break;
default:
addString(ch);
+ String str = new String(getChars(0, strpos));
+ if (!insideComment && str.endsWith(START_COMMENT)) {
+ insideComment = true;
+ }
+ if (insideComment && str.endsWith(END_COMMENT)) {
+ insideComment = false;
+ }
ch = readCh();
break;
} // switch
--- a/jdk/src/share/classes/sun/management/Agent.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/sun/management/Agent.java Mon Jun 03 23:23:20 2013 -0700
@@ -77,7 +77,7 @@
private static final String SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME =
"sun.management.snmp.AdaptorBootstrap";
- private static final String JDP_DEFAULT_ADDRESS = "239.255.255.225";
+ private static final String JDP_DEFAULT_ADDRESS = "224.0.23.178";
private static final int JDP_DEFAULT_PORT = 7095;
// The only active agent allowed
--- a/jdk/src/share/classes/sun/management/jdp/package-info.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/sun/management/jdp/package-info.java Mon Jun 03 23:23:20 2013 -0700
@@ -60,7 +60,7 @@
*
* - `INSTANCE_NAME` -- The user-provided name of the running instance
*
- * The protocol sends packets to 239.255.255.225:7095 by default.
+ * The protocol sends packets to 224.0.23.178:7095 by default.
*
* The protocol uses system properties to control it's behaviour:
* - `com.sun.management.jdp.port` -- override default port
--- a/jdk/src/share/classes/sun/nio/cs/UTF_8.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/UTF_8.java Mon Jun 03 23:23:20 2013 -0700
@@ -682,6 +682,11 @@
return encodeBufferLoop(src, dst);
}
+ private byte repl = (byte)'?';
+ protected void implReplaceWith(byte[] newReplacement) {
+ repl = newReplacement[0];
+ }
+
// returns -1 if there is malformed char(s) and the
// "action" for malformed input is not REPLACE.
public int encode(char[] sa, int sp, int len, byte[] da) {
@@ -709,7 +714,7 @@
if (uc < 0) {
if (malformedInputAction() != CodingErrorAction.REPLACE)
return -1;
- da[dp++] = replacement()[0];
+ da[dp++] = repl;
} else {
da[dp++] = (byte)(0xf0 | ((uc >> 18)));
da[dp++] = (byte)(0x80 | ((uc >> 12) & 0x3f));
--- a/jdk/src/share/classes/sun/nio/cs/ext/DoubleByte.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/ext/DoubleByte.java Mon Jun 03 23:23:20 2013 -0700
@@ -610,6 +610,11 @@
return encodeBufferLoop(src, dst);
}
+ protected byte[] repl = replacement();
+ protected void implReplaceWith(byte[] newReplacement) {
+ repl = newReplacement;
+ }
+
public int encode(char[] src, int sp, int len, byte[] dst) {
int dp = 0;
int sl = sp + len;
@@ -622,7 +627,6 @@
Character.isLowSurrogate(src[sp])) {
sp++;
}
- byte[] repl = replacement();
dst[dp++] = repl[0];
if (repl.length > 1)
dst[dp++] = repl[1];
@@ -877,7 +881,6 @@
Character.isLowSurrogate(src[sp])) {
sp++;
}
- byte[] repl = replacement();
dst[dp++] = repl[0];
if (repl.length > 1)
dst[dp++] = repl[1];
--- a/jdk/src/share/classes/sun/nio/cs/ext/HKSCS.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/ext/HKSCS.java Mon Jun 03 23:23:20 2013 -0700
@@ -356,6 +356,11 @@
return encodeBufferLoop(src, dst);
}
+ private byte[] repl = replacement();
+ protected void implReplaceWith(byte[] newReplacement) {
+ repl = newReplacement;
+ }
+
public int encode(char[] src, int sp, int len, byte[] dst) {
int dp = 0;
int sl = sp + len;
@@ -367,7 +372,6 @@
!Character.isLowSurrogate(src[sp]) ||
(bb = encodeSupp(Character.toCodePoint(c, src[sp++])))
== UNMAPPABLE_ENCODING) {
- byte[] repl = replacement();
dst[dp++] = repl[0];
if (repl.length > 1)
dst[dp++] = repl[1];
--- a/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java Mon Jun 03 23:23:20 2013 -0700
@@ -78,7 +78,7 @@
private final String tabName;
private long lastModified;
- private int kt_vno;
+ private int kt_vno = KRB5_KT_VNO;
private Vector<KeyTabEntry> entries = new Vector<>();
--- a/jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java Mon Jun 03 23:23:20 2013 -0700
@@ -552,7 +552,7 @@
try {
Signature respSignature = Signature.getInstance(sigAlgId.getName());
- respSignature.initVerify(cert);
+ respSignature.initVerify(cert.getPublicKey());
respSignature.update(tbsResponseData);
if (respSignature.verify(signature)) {
--- a/jdk/src/share/classes/sun/security/tools/policytool/PolicyTool.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/sun/security/tools/policytool/PolicyTool.java Mon Jun 03 23:23:20 2013 -0700
@@ -1447,6 +1447,7 @@
PERM_ARRAY.add(new AWTPerm());
PERM_ARRAY.add(new DelegationPerm());
PERM_ARRAY.add(new FilePerm());
+ PERM_ARRAY.add(new HttpURLPerm());
PERM_ARRAY.add(new InqSecContextPerm());
PERM_ARRAY.add(new LogPerm());
PERM_ARRAY.add(new MgmtPerm());
@@ -3842,6 +3843,20 @@
}
}
+class HttpURLPerm extends Perm {
+ public HttpURLPerm() {
+ super("HttpURLPermission",
+ "java.net.HttpURLPermission",
+ new String[] {
+ "<"+ PolicyTool.rb.getString("url") + ">",
+ },
+ new String[] {
+ "<" + PolicyTool.rb.getString("method.list") + ">:<"
+ + PolicyTool.rb.getString("request.headers.list") + ">",
+ });
+ }
+}
+
class InqSecContextPerm extends Perm {
public InqSecContextPerm() {
super("InquireSecContextPermission",
--- a/jdk/src/share/classes/sun/security/tools/policytool/Resources.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/sun/security/tools/policytool/Resources.java Mon Jun 03 23:23:20 2013 -0700
@@ -139,6 +139,9 @@
{"policy.type", "policy type"},
{"property.name", "property name"},
{"provider.name", "provider name"},
+ {"url", "url"},
+ {"method.list", "method list"},
+ {"request.headers.list", "request headers list"},
{"Principal.List", "Principal List"},
{"Permission.List", "Permission List"},
{"Code.Base", "Code Base"},
--- a/jdk/src/share/classes/sun/text/resources/mt/FormatData_mt.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/sun/text/resources/mt/FormatData_mt.java Mon Jun 03 23:23:20 2013 -0700
@@ -54,7 +54,7 @@
"Mejju",
"\u0120unju",
"Lulju",
- "Awissu",
+ "Awwissu",
"Settembru",
"Ottubru",
"Novembru",
@@ -71,7 +71,7 @@
"Mej",
"\u0120un",
"Lul",
- "Awi",
+ "Aww",
"Set",
"Ott",
"Nov",
--- a/jdk/src/share/classes/sun/tools/jconsole/AboutDialog.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/sun/tools/jconsole/AboutDialog.java Mon Jun 03 23:23:20 2013 -0700
@@ -34,6 +34,7 @@
import javax.swing.border.*;
import javax.swing.event.*;
+import static sun.misc.Version.jdkMinorVersion;
import static java.awt.BorderLayout.*;
import static sun.tools.jconsole.Utilities.*;
@@ -73,7 +74,7 @@
String jConsoleVersion = Version.getVersion();
String vmName = System.getProperty("java.vm.name");
String vmVersion = System.getProperty("java.vm.version");
- String urlStr = Messages.HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL;
+ String urlStr = getOnlineDocUrl();
if (isBrowseSupported()) {
urlStr = "<a style='color:#35556b' href=\"" + urlStr + "\">" + urlStr + "</a>";
}
@@ -86,8 +87,7 @@
"<html><font color=#"+ colorStr + ">" +
Resources.format(Messages.HELP_ABOUT_DIALOG_JCONSOLE_VERSION, jConsoleVersion) +
"<p>" + Resources.format(Messages.HELP_ABOUT_DIALOG_JAVA_VERSION, (vmName +", "+ vmVersion)) +
- "<p>" + Resources.format(Messages.HELP_ABOUT_DIALOG_USER_GUIDE_LINK, urlStr) +
- "</html>");
+ "<p>" + urlStr + "</html>");
helpLink.setOpaque(false);
helpLink.setEditable(false);
helpLink.setForeground(textColor);
@@ -153,7 +153,7 @@
}
static void browseUserGuide(JConsole jConsole) {
- getAboutDialog(jConsole).browse(Messages.HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL);
+ getAboutDialog(jConsole).browse(getOnlineDocUrl());
}
static boolean isBrowseSupported() {
@@ -182,6 +182,12 @@
};
}
+ private static String getOnlineDocUrl() {
+ String version = Integer.toString(jdkMinorVersion());
+ return Resources.format(Messages.HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL,
+ version);
+ }
+
private static class TPanel extends JPanel {
TPanel(int hgap, int vgap) {
super(new BorderLayout(hgap, vgap));
--- a/jdk/src/share/classes/sun/tools/jconsole/VMPanel.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/sun/tools/jconsole/VMPanel.java Mon Jun 03 23:23:20 2013 -0700
@@ -55,6 +55,7 @@
private VMInternalFrame vmIF = null;
private static ArrayList<TabInfo> tabInfos = new ArrayList<TabInfo>();
private boolean wasConnected = false;
+ private boolean userDisconnected = false;
// The everConnected flag keeps track of whether the window can be
// closed if the user clicks Cancel after a failed connection attempt.
@@ -125,6 +126,7 @@
if (connectedIconBounds != null && (e.getModifiers() & MouseEvent.BUTTON1_MASK) != 0 && connectedIconBounds.contains(e.getPoint())) {
if (isConnected()) {
+ userDisconnected = true;
disconnect();
wasConnected = false;
} else {
@@ -452,6 +454,11 @@
private void vmPanelDied() {
disconnect();
+ if (userDisconnected) {
+ userDisconnected = false;
+ return;
+ }
+
JOptionPane optionPane;
String msgTitle, msgExplanation, buttonStr;
--- a/jdk/src/share/classes/sun/tools/jconsole/resources/messages.properties Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/sun/tools/jconsole/resources/messages.properties Mon Jun 03 23:23:20 2013 -0700
@@ -105,7 +105,7 @@
HELP_ABOUT_DIALOG_MASTHEAD_TITLE=About JConsole
HELP_ABOUT_DIALOG_TITLE=JConsole: About
HELP_ABOUT_DIALOG_USER_GUIDE_LINK=JConsole &User Guide:<br>{0}
-HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL=http://java.sun.com/javase/6/docs/technotes/guides/management/jconsole.html
+HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL=http://docs.oracle.com/javase/{0}/docs/technotes/guides/management/jconsole.html
HELP_MENU_ABOUT_TITLE=&About JConsole
HELP_MENU_USER_GUIDE_TITLE=Online &User Guide
HELP_MENU_TITLE=&Help
--- a/jdk/src/share/classes/sun/tools/jconsole/resources/messages_ja.properties Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/sun/tools/jconsole/resources/messages_ja.properties Mon Jun 03 23:23:20 2013 -0700
@@ -105,7 +105,7 @@
HELP_ABOUT_DIALOG_MASTHEAD_TITLE=JConsole\u306B\u3064\u3044\u3066
HELP_ABOUT_DIALOG_TITLE=JConsole: \u8A73\u7D30
HELP_ABOUT_DIALOG_USER_GUIDE_LINK=JConsole\u30E6\u30FC\u30B6\u30FC\u30FB\u30AC\u30A4\u30C9(&U):<br>{0}
-HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL=http://java.sun.com/javase/6/docs/technotes/guides/management/jconsole.html
+HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL=http://docs.oracle.com/javase/{0}/docs/technotes/guides/management/jconsole.html
HELP_MENU_ABOUT_TITLE=JConsole\u306B\u3064\u3044\u3066(&A)
HELP_MENU_USER_GUIDE_TITLE=\u30AA\u30F3\u30E9\u30A4\u30F3\u30FB\u30E6\u30FC\u30B6\u30FC\u30FB\u30AC\u30A4\u30C9(&U)
HELP_MENU_TITLE=\u30D8\u30EB\u30D7(&H)
--- a/jdk/src/share/classes/sun/tools/jconsole/resources/messages_zh_CN.properties Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/classes/sun/tools/jconsole/resources/messages_zh_CN.properties Mon Jun 03 23:23:20 2013 -0700
@@ -105,7 +105,7 @@
HELP_ABOUT_DIALOG_MASTHEAD_TITLE=\u5173\u4E8E JConsole
HELP_ABOUT_DIALOG_TITLE=JConsole: \u5173\u4E8E
HELP_ABOUT_DIALOG_USER_GUIDE_LINK=JConsole \u7528\u6237\u6307\u5357(&U):<br>{0}
-HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL=http://java.sun.com/javase/6/docs/technotes/guides/management/jconsole.html
+HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL=http://docs.oracle.com/javase/{0}/docs/technotes/guides/management/jconsole.html
HELP_MENU_ABOUT_TITLE=\u5173\u4E8E JConsole(&A)
HELP_MENU_USER_GUIDE_TITLE=\u8054\u673A\u7528\u6237\u6307\u5357(&U)
HELP_MENU_TITLE=\u5E2E\u52A9(&H)
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java Mon Jun 03 23:23:20 2013 -0700
@@ -1085,13 +1085,13 @@
}
// Creates a new empty temporary file in the same directory as the
- // specified file. A variant of File.createTempFile.
+ // specified file. A variant of Files.createTempFile.
private Path createTempFileInSameDirectoryAs(Path path)
throws IOException
{
Path parent = path.toAbsolutePath().getParent();
- String dir = (parent == null)? "." : parent.toString();
- Path tmpPath = File.createTempFile("zipfstmp", null, new File(dir)).toPath();
+ Path dir = (parent == null) ? path.getFileSystem().getPath(".") : parent;
+ Path tmpPath = Files.createTempFile(dir, "zipfstmp", null);
tmppaths.add(tmpPath);
return tmpPath;
}
--- a/jdk/src/share/native/java/io/FileInputStream.c Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/native/java/io/FileInputStream.c Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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
@@ -100,6 +100,8 @@
if (IO_Available(fd, &ret)) {
if (ret > INT_MAX) {
ret = (jlong) INT_MAX;
+ } else if (ret < 0) {
+ ret = 0;
}
return jlong_to_jint(ret);
}
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmscgats.c Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmscgats.c Mon Jun 03 23:23:20 2013 -0700
@@ -634,6 +634,8 @@
cmsFloat64Number dnum = 0.0;
int sign = 1;
+ if (Buffer == NULL) return 0.0;
+
if (*Buffer == '-' || *Buffer == '+') {
sign = (*Buffer == '-') ? -1 : 1;
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmslut.c Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmslut.c Mon Jun 03 23:23:20 2013 -0700
@@ -1021,6 +1021,8 @@
mpe = cmsStageAllocToneCurves(ContextID, 3, LabTable);
cmsFreeToneCurveTriple(LabTable);
+ if (mpe == NULL) return NULL;
+
mpe ->Implements = cmsSigLabV2toV4;
return mpe;
}
--- a/jdk/src/solaris/bin/arm/jvm.cfg Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/solaris/bin/arm/jvm.cfg Mon Jun 03 23:23:20 2013 -0700
@@ -30,6 +30,6 @@
# "-XXaltjvm=<jvm_dir>" option, but that too is unsupported
# and may not be available in a future release.
#
--client KNOWN
+-client IF_SERVER_CLASS -server
-server KNOWN
-minimal KNOWN
--- a/jdk/src/solaris/classes/sun/awt/X11/MotifDnDConstants.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/MotifDnDConstants.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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
@@ -190,7 +190,7 @@
try {
Native.putLong(data, motifWindow);
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XlibWrapper.XChangeProperty(XToolkit.getDisplay(),
defaultRootWindow,
XA_MOTIF_DRAG_WINDOW.getAtom(),
@@ -198,10 +198,10 @@
XConstants.PropModeReplace,
data, 1);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("Cannot write motif drag window handle.");
}
@@ -394,7 +394,7 @@
}
}
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XlibWrapper.XChangeProperty(XToolkit.getDisplay(),
motifWindow,
XA_MOTIF_DRAG_TARGETS.getAtom(),
@@ -402,15 +402,15 @@
XConstants.PropModeReplace,
data, tableSize);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
// Create a new motif window and retry.
motifWindow = createMotifWindow();
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XlibWrapper.XChangeProperty(XToolkit.getDisplay(),
motifWindow,
XA_MOTIF_DRAG_TARGETS.getAtom(),
@@ -418,10 +418,10 @@
XConstants.PropModeReplace,
data, tableSize);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("Cannot write motif drag targets property.");
}
}
@@ -534,16 +534,16 @@
// CARD32 icc_handle
unsafe.putInt(structData + 4, (int)XA_MOTIF_ATOM_0.getAtom());
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XlibWrapper.XChangeProperty(XToolkit.getDisplay(), window,
XA_MOTIF_ATOM_0.getAtom(),
XA_MOTIF_DRAG_INITIATOR_INFO.getAtom(),
8, XConstants.PropModeReplace,
structData, MOTIF_INITIATOR_INFO_SIZE);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("Cannot write drag initiator info");
}
} finally {
@@ -567,16 +567,16 @@
unsafe.putShort(data + 10, (short)0); /* pad */
unsafe.putInt(data + 12, dataSize);
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XlibWrapper.XChangeProperty(XToolkit.getDisplay(), window,
XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
8, XConstants.PropModeReplace,
data, dataSize);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("Cannot write Motif receiver info property");
}
} finally {
--- a/jdk/src/solaris/classes/sun/awt/X11/MotifDnDDropTargetProtocol.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/MotifDnDDropTargetProtocol.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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
@@ -162,16 +162,16 @@
unsafe.putInt(data + 12, dataSize);
}
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XlibWrapper.XChangeProperty(XToolkit.getDisplay(), embedder,
MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
8, XConstants.PropModeReplace,
data, dataSize);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("Cannot write Motif receiver info property");
}
} finally {
@@ -236,16 +236,16 @@
unsafe.putInt(data + 4, tproxy);
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XlibWrapper.XChangeProperty(XToolkit.getDisplay(), embedder,
MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
8, XConstants.PropModeReplace,
data, dataSize);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("Cannot write Motif receiver info property");
}
}
@@ -412,15 +412,15 @@
*/
XWindowAttributes wattr = new XWindowAttributes();
try {
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
source_win, wattr.pData);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (status == 0 ||
- (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success)) {
+ if ((status == 0) ||
+ ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success))) {
throw new XException("XGetWindowAttributes failed");
}
@@ -429,15 +429,15 @@
wattr.dispose();
}
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
XlibWrapper.XSelectInput(XToolkit.getDisplay(), source_win,
source_win_mask |
XConstants.StructureNotifyMask);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("XSelectInput failed");
}
@@ -1024,10 +1024,10 @@
if (sourceWindow != 0) {
XToolkit.awtLock();
try {
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
XlibWrapper.XSelectInput(XToolkit.getDisplay(), sourceWindow,
sourceWindowMask);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
} finally {
XToolkit.awtUnlock();
}
--- a/jdk/src/solaris/classes/sun/awt/X11/WindowPropertyGetter.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/WindowPropertyGetter.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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
@@ -99,7 +99,7 @@
}
if (errorHandler != null) {
- XToolkit.WITH_XERROR_HANDLER(errorHandler);
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(errorHandler);
}
Native.putLong(data, 0);
int status = XlibWrapper.XGetWindowProperty(XToolkit.getDisplay(), window, property.getAtom(),
@@ -112,7 +112,7 @@
}
if (errorHandler != null) {
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
}
return status;
} finally {
--- a/jdk/src/solaris/classes/sun/awt/X11/XConstants.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XConstants.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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
@@ -674,4 +674,9 @@
public static final long XkbModifierMapMask = (1L<<2);
public static final long XkbVirtualModsMask = (1L<<6); //server map
+ /*****************************************************************
+ * X SHARED MEMORY EXTENSION FUNCTIONS
+ *****************************************************************/
+
+ public static final int X_ShmAttach = 1;
}
--- a/jdk/src/solaris/classes/sun/awt/X11/XDnDDragSourceProtocol.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XDnDDragSourceProtocol.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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
@@ -96,14 +96,14 @@
action_count++;
}
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XDnDConstants.XA_XdndActionList.setAtomData(window,
XAtom.XA_ATOM,
data, action_count);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error) != null &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
cleanup();
throw new XException("Cannot write XdndActionList property");
}
@@ -117,14 +117,14 @@
try {
Native.put(data, formats);
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XDnDConstants.XA_XdndTypeList.setAtomData(window,
XAtom.XA_ATOM,
data, formats.length);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
cleanup();
throw new XException("Cannot write XdndActionList property");
}
--- a/jdk/src/solaris/classes/sun/awt/X11/XDnDDropTargetProtocol.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XDnDDropTargetProtocol.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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
@@ -88,12 +88,12 @@
try {
Native.putLong(data, 0, XDnDConstants.XDND_PROTOCOL_VERSION);
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XDnDConstants.XA_XdndAware.setAtomData(window, XAtom.XA_ATOM, data, 1);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("Cannot write XdndAware property");
}
} finally {
@@ -205,54 +205,50 @@
/* The proxy window must have the XdndAware set, as XDnD protocol
prescribes to check the proxy window for XdndAware. */
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XDnDConstants.XA_XdndAware.setAtomData(newProxy, XAtom.XA_ATOM,
data, 1);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() !=
- XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("Cannot write XdndAware property");
}
Native.putLong(data, 0, newProxy);
/* The proxy window must have the XdndProxy set to point to itself.*/
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XDnDConstants.XA_XdndProxy.setAtomData(newProxy, XAtom.XA_WINDOW,
data, 1);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() !=
- XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("Cannot write XdndProxy property");
}
Native.putLong(data, 0, XDnDConstants.XDND_PROTOCOL_VERSION);
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XDnDConstants.XA_XdndAware.setAtomData(embedder, XAtom.XA_ATOM,
data, 1);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() !=
- XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("Cannot write XdndAware property");
}
Native.putLong(data, 0, newProxy);
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XDnDConstants.XA_XdndProxy.setAtomData(embedder, XAtom.XA_WINDOW,
data, 1);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() !=
- XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("Cannot write XdndProxy property");
}
} finally {
@@ -278,27 +274,25 @@
try {
Native.putLong(data, 0, entry.getVersion());
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XDnDConstants.XA_XdndAware.setAtomData(embedder, XAtom.XA_ATOM,
data, 1);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() !=
- XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("Cannot write XdndAware property");
}
Native.putLong(data, 0, (int)entry.getProxy());
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XDnDConstants.XA_XdndProxy.setAtomData(embedder, XAtom.XA_WINDOW,
data, 1);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() !=
- XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("Cannot write XdndProxy property");
}
} finally {
@@ -541,15 +535,15 @@
*/
XWindowAttributes wattr = new XWindowAttributes();
try {
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
source_win, wattr.pData);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (status == 0 ||
- (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success)) {
+ if ((status == 0) ||
+ ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success))) {
throw new XException("XGetWindowAttributes failed");
}
@@ -558,15 +552,15 @@
wattr.dispose();
}
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
XlibWrapper.XSelectInput(XToolkit.getDisplay(), source_win,
source_win_mask |
XConstants.StructureNotifyMask);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("XSelectInput failed");
}
@@ -963,10 +957,10 @@
if (sourceWindow != 0) {
XToolkit.awtLock();
try {
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
XlibWrapper.XSelectInput(XToolkit.getDisplay(), sourceWindow,
sourceWindowMask);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
} finally {
XToolkit.awtUnlock();
}
@@ -1111,15 +1105,15 @@
XToolkit.awtLock();
try {
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XDnDConstants.XA_XdndTypeList.setAtomData(xclient.get_window(),
XAtom.XA_ATOM,
wpg.getData(),
wpg.getNumberOfItems());
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
if (logger.isLoggable(PlatformLogger.WARNING)) {
logger.warning("Cannot set XdndTypeList on the proxy window");
}
--- a/jdk/src/solaris/classes/sun/awt/X11/XDragSourceProtocol.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XDragSourceProtocol.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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
@@ -181,15 +181,15 @@
long time) {
XWindowAttributes wattr = new XWindowAttributes();
try {
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
targetWindow, wattr.pData);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (status == 0 ||
- (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success)) {
+ if ((status == 0) ||
+ ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success))) {
throw new XException("XGetWindowAttributes failed");
}
@@ -198,15 +198,15 @@
wattr.dispose();
}
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
XlibWrapper.XSelectInput(XToolkit.getDisplay(), targetWindow,
targetWindowMask |
XConstants.StructureNotifyMask);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("XSelectInput failed");
}
@@ -214,10 +214,10 @@
}
protected final void finalizeDrop() {
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
XlibWrapper.XSelectInput(XToolkit.getDisplay(), targetWindow,
targetWindowMask);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
}
public abstract boolean processProxyModeEvent(XClientMessageEvent xclient,
--- a/jdk/src/solaris/classes/sun/awt/X11/XDropTargetRegistry.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XDropTargetRegistry.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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
@@ -168,14 +168,14 @@
if (dest_x >= 0 && dest_y >= 0) {
XWindowAttributes wattr = new XWindowAttributes();
try {
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
window, wattr.pData);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (status == 0 ||
- (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success)) {
+ if ((status == 0) ||
+ ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success))) {
continue;
}
@@ -222,14 +222,14 @@
long event_mask = 0;
XWindowAttributes wattr = new XWindowAttributes();
try {
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
embedder, wattr.pData);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (status == 0 ||
- (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success)) {
+ if ((status == 0) ||
+ ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success))) {
throw new XException("XGetWindowAttributes failed");
}
@@ -240,13 +240,13 @@
}
if ((event_mask & XConstants.PropertyChangeMask) == 0) {
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
XlibWrapper.XSelectInput(XToolkit.getDisplay(), embedder,
event_mask | XConstants.PropertyChangeMask);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("XSelectInput failed");
}
}
@@ -394,13 +394,13 @@
/* Restore the original event mask for the embedder. */
if ((event_mask & XConstants.PropertyChangeMask) == 0) {
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
XlibWrapper.XSelectInput(XToolkit.getDisplay(), embedder,
event_mask);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("XSelectInput failed");
}
}
--- a/jdk/src/solaris/classes/sun/awt/X11/XEmbedCanvasPeer.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XEmbedCanvasPeer.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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
@@ -301,15 +301,15 @@
try {
XWindowAttributes wattr = new XWindowAttributes();
try {
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
xembed.handle, wattr.pData);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (status == 0 ||
- (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success)) {
+ if ((status == 0) ||
+ ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success))) {
return null;
}
--- a/jdk/src/solaris/classes/sun/awt/X11/XErrorHandler.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XErrorHandler.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -38,7 +38,30 @@
public static class XBaseErrorHandler extends XErrorHandler {
@Override
public int handleError(long display, XErrorEvent err) {
- return XToolkit.SAVED_ERROR_HANDLER(display, err);
+ return XErrorHandlerUtil.SAVED_XERROR_HANDLER(display, err);
+ }
+ }
+
+ /**
+ * This is a base synthetic error handler containing a boolean flag which allows
+ * to show that an error is handled or not.
+ */
+ public static class XErrorHandlerWithFlag extends XBaseErrorHandler {
+ private volatile boolean errorOccurred = false;
+
+ public boolean getErrorOccurredFlag() {
+ return errorOccurred;
+ }
+
+ /**
+ * Sets an internal boolean flag to a particular value. Should be always called with
+ * <code>false</code> value of the parameter <code>errorOccurred</code> before this
+ * error handler is set as current.
+ * @param errorOccurred <code>true</code> to indicate that an error was handled,
+ * <code>false</code> to reset the internal boolean flag
+ */
+ public void setErrorOccurredFlag(boolean errorOccurred) {
+ this.errorOccurred = errorOccurred;
}
}
@@ -76,4 +99,51 @@
return theInstance;
}
}
+
+ /**
+ * This is a synthetic error handler for errors generated by the native function
+ * <code>XShmAttach</code>. If an error is handled, an internal boolean flag of the
+ * handler is set to <code>true</code>.
+ */
+ public static final class XShmAttachHandler extends XErrorHandlerWithFlag {
+ private XShmAttachHandler() {}
+
+ @Override
+ public int handleError(long display, XErrorEvent err) {
+ if (err.get_minor_code() == XConstants.X_ShmAttach) {
+ setErrorOccurredFlag(true);
+ return 0;
+ }
+ return super.handleError(display, err);
+ }
+
+ // Shared instance
+ private static XShmAttachHandler theInstance = new XShmAttachHandler();
+ public static XShmAttachHandler getInstance() {
+ return theInstance;
+ }
+ }
+
+ /**
+ * This is a synthetic error handler for <code>BadAlloc</code> errors generated by the
+ * native <code>glX*</code> functions. Its internal boolean flag is set to <code>true</code>,
+ * if an error is handled.
+ */
+ public static final class GLXBadAllocHandler extends XErrorHandlerWithFlag {
+ private GLXBadAllocHandler() {}
+
+ @Override
+ public int handleError(long display, XErrorEvent err) {
+ if (err.get_error_code() == XConstants.BadAlloc) {
+ setErrorOccurredFlag(true);
+ return 0;
+ }
+ return super.handleError(display, err);
+ }
+
+ private static GLXBadAllocHandler theInstance = new GLXBadAllocHandler();
+ public static GLXBadAllocHandler getInstance() {
+ return theInstance;
+ }
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/awt/X11/XErrorHandlerUtil.java Mon Jun 03 23:23:20 2013 -0700
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.awt.X11;
+
+import java.security.AccessController;
+import sun.awt.SunToolkit;
+import sun.security.action.GetBooleanAction;
+import sun.util.logging.PlatformLogger;
+
+/**
+ * This class contains code of the global toolkit error handler, exposes static
+ * methods which allow to set and unset synthetic error handlers.
+ */
+public final class XErrorHandlerUtil {
+ private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XErrorHandlerUtil");
+
+ /**
+ * The connection to X11 window server.
+ */
+ private static long display;
+
+ /**
+ * Error handler at the moment of <code>XErrorHandlerUtil</code> initialization.
+ */
+ private static long saved_error_handler;
+
+ /**
+ * XErrorEvent being handled.
+ */
+ static volatile XErrorEvent saved_error;
+
+ /**
+ * Current error handler or null if no error handler is set.
+ */
+ private static XErrorHandler current_error_handler;
+
+ /**
+ * Value of sun.awt.noisyerrorhandler system property.
+ */
+ private static boolean noisyAwtHandler = AccessController.doPrivileged(
+ new GetBooleanAction("sun.awt.noisyerrorhandler"));
+
+ /**
+ * The flag indicating that <code>init</code> was called already.
+ */
+ private static boolean initPassed;
+
+ /**
+ * Guarantees that no instance of this class can be created.
+ */
+ private XErrorHandlerUtil() {}
+
+ /**
+ * Sets the toolkit global error handler, stores the connection to X11 server, which
+ * will be used during an error handling process. This method is called once from
+ * <code>awt_init_Display</code> function defined in <code>awt_GraphicsEnv.c</code>
+ * file immediately after the connection to X11 window server is opened.
+ * @param display the connection to X11 server which should be stored
+ */
+ private static void init(long display) {
+ SunToolkit.awtLock();
+ try {
+ if (!initPassed) {
+ XErrorHandlerUtil.display = display;
+ saved_error_handler = XlibWrapper.SetToolkitErrorHandler();
+ initPassed = true;
+ }
+ } finally {
+ SunToolkit.awtUnlock();
+ }
+ }
+
+ /**
+ * Sets a synthetic error handler. Must be called with the acquired AWT lock.
+ * @param handler the synthetic error handler to set
+ */
+ public static void WITH_XERROR_HANDLER(XErrorHandler handler) {
+ saved_error = null;
+ current_error_handler = handler;
+ }
+
+ /**
+ * Unsets a current synthetic error handler. Must be called with the acquired AWT lock.
+ */
+ public static void RESTORE_XERROR_HANDLER() {
+ // Wait until all requests are processed by the X server
+ // and only then uninstall the error handler.
+ XSync();
+ current_error_handler = null;
+ }
+
+ /**
+ * Should be called under LOCK.
+ */
+ public static int SAVED_XERROR_HANDLER(long display, XErrorEvent error) {
+ if (saved_error_handler != 0) {
+ // Default XErrorHandler may just terminate the process. Don't call it.
+ // return XlibWrapper.CallErrorHandler(saved_error_handler, display, error.pData);
+ }
+ if (log.isLoggable(PlatformLogger.FINE)) {
+ log.fine("Unhandled XErrorEvent: " +
+ "id=" + error.get_resourceid() + ", " +
+ "serial=" + error.get_serial() + ", " +
+ "ec=" + error.get_error_code() + ", " +
+ "rc=" + error.get_request_code() + ", " +
+ "mc=" + error.get_minor_code());
+ }
+ return 0;
+ }
+
+ /**
+ * Called from the native code when an error occurs.
+ */
+ private static int globalErrorHandler(long display, long event_ptr) {
+ if (noisyAwtHandler) {
+ XlibWrapper.PrintXErrorEvent(display, event_ptr);
+ }
+ XErrorEvent event = new XErrorEvent(event_ptr);
+ saved_error = event;
+ try {
+ if (current_error_handler != null) {
+ return current_error_handler.handleError(display, event);
+ } else {
+ return SAVED_XERROR_HANDLER(display, event);
+ }
+ } catch (Throwable z) {
+ log.fine("Error in GlobalErrorHandler", z);
+ }
+ return 0;
+ }
+
+ private static void XSync() {
+ SunToolkit.awtLock();
+ try {
+ XlibWrapper.XSync(display, 0);
+ } finally {
+ SunToolkit.awtUnlock();
+ }
+ }
+}
--- a/jdk/src/solaris/classes/sun/awt/X11/XQueryTree.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XQueryTree.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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
@@ -61,7 +61,7 @@
}
__executed = true;
if (errorHandler != null) {
- XToolkit.WITH_XERROR_HANDLER(errorHandler);
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(errorHandler);
}
Native.putLong(children_ptr, 0);
int status =
@@ -72,7 +72,7 @@
children_ptr,
nchildren_ptr );
if (errorHandler != null) {
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
}
return status;
} finally {
--- a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2013, Oracle and/or its affiliates. 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
@@ -128,7 +128,6 @@
initIDs();
setBackingStoreType();
}
- noisyAwtHandler = AccessController.doPrivileged(new GetBooleanAction("sun.awt.noisyerrorhandler"));
}
/*
@@ -137,78 +136,6 @@
*/
static native long getTrayIconDisplayTimeout();
- //---- ERROR HANDLER CODE ----//
-
- /*
- * Error handler at the moment of XToolkit initialization
- */
- private static long saved_error_handler;
-
- /*
- * XErrorEvent being handled
- */
- static volatile XErrorEvent saved_error;
-
- /*
- * Current error handler or null if no error handler is set
- */
- private static XErrorHandler current_error_handler;
-
- /*
- * Value of sun.awt.noisyerrorhandler system property
- */
- private static boolean noisyAwtHandler;
-
- public static void WITH_XERROR_HANDLER(XErrorHandler handler) {
- saved_error = null;
- current_error_handler = handler;
- }
-
- public static void RESTORE_XERROR_HANDLER() {
- // wait until all requests are processed by the X server
- // and only then uninstall the error handler
- XSync();
- current_error_handler = null;
- }
-
- // Should be called under LOCK
- public static int SAVED_ERROR_HANDLER(long display, XErrorEvent error) {
- if (saved_error_handler != 0) {
- // Default XErrorHandler may just terminate the process. Don't call it.
- // return XlibWrapper.CallErrorHandler(saved_error_handler, display, error.pData);
- }
- if (log.isLoggable(PlatformLogger.FINE)) {
- log.fine("Unhandled XErrorEvent: " +
- "id=" + error.get_resourceid() + ", " +
- "serial=" + error.get_serial() + ", " +
- "ec=" + error.get_error_code() + ", " +
- "rc=" + error.get_request_code() + ", " +
- "mc=" + error.get_minor_code());
- }
- return 0;
- }
-
- // Called from the native code when an error occurs
- private static int globalErrorHandler(long display, long event_ptr) {
- if (noisyAwtHandler) {
- XlibWrapper.PrintXErrorEvent(display, event_ptr);
- }
- XErrorEvent event = new XErrorEvent(event_ptr);
- saved_error = event;
- try {
- if (current_error_handler != null) {
- return current_error_handler.handleError(display, event);
- } else {
- return SAVED_ERROR_HANDLER(display, event);
- }
- } catch (Throwable z) {
- log.fine("Error in GlobalErrorHandler", z);
- }
- return 0;
- }
-
- //---- END OF ERROR HANDLER CODE ----//
-
private native static void initIDs();
native static void waitForEvents(long nextTaskTime);
static Thread toolkitThread;
@@ -306,8 +233,6 @@
//set system property if not yet assigned
System.setProperty("sun.awt.enableExtraMouseButtons", ""+areExtraMouseButtonsEnabled);
- saved_error_handler = XlibWrapper.SetToolkitErrorHandler();
-
// Detect display mode changes
XlibWrapper.XSelectInput(XToolkit.getDisplay(), XToolkit.getDefaultRootWindow(), XConstants.StructureNotifyMask);
XToolkit.addEventDispatcher(XToolkit.getDefaultRootWindow(), new XEventDispatcher() {
--- a/jdk/src/solaris/classes/sun/awt/X11/XTranslateCoordinates.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XTranslateCoordinates.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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
@@ -68,7 +68,7 @@
}
__executed = true;
if (errorHandler != null) {
- XToolkit.WITH_XERROR_HANDLER(errorHandler);
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(errorHandler);
}
int status =
XlibWrapper.XTranslateCoordinates(XToolkit.getDisplay(),
@@ -80,7 +80,7 @@
dest_y_ptr,
child_ptr );
if (errorHandler != null) {
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
}
return status;
} finally {
--- a/jdk/src/solaris/classes/sun/awt/X11/XWM.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XWM.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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
@@ -284,12 +284,12 @@
winmgr_running = false;
substruct.set_event_mask(XConstants.SubstructureRedirectMask);
- XToolkit.WITH_XERROR_HANDLER(detectWMHandler);
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(detectWMHandler);
XlibWrapper.XChangeWindowAttributes(XToolkit.getDisplay(),
XToolkit.getDefaultRootWindow(),
XConstants.CWEventMask,
substruct.pData);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
/*
* If no WM is running then our selection for SubstructureRedirect
@@ -632,15 +632,16 @@
XToolkit.awtLock();
try {
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XlibWrapper.XChangePropertyS(XToolkit.getDisplay(), XToolkit.getDefaultRootWindow(),
XA_ICEWM_WINOPTHINT.getAtom(),
XA_ICEWM_WINOPTHINT.getAtom(),
8, XConstants.PropModeReplace,
new String(opt));
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null && XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
log.finer("Erorr getting XA_ICEWM_WINOPTHINT property");
return false;
}
--- a/jdk/src/solaris/classes/sun/awt/X11/XlibUtil.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XlibUtil.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2013, Oracle and/or its affiliates. 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
@@ -151,8 +151,8 @@
{
int status = xtc.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
if ((status != 0) &&
- ((XToolkit.saved_error == null) ||
- (XToolkit.saved_error.get_error_code() == XConstants.Success)))
+ ((XErrorHandlerUtil.saved_error == null) ||
+ (XErrorHandlerUtil.saved_error.get_error_code() == XConstants.Success)))
{
translated = new Point(xtc.get_dest_x(), xtc.get_dest_y());
}
@@ -345,13 +345,13 @@
XWindowAttributes wattr = new XWindowAttributes();
try
{
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
window, wattr.pData);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
if ((status != 0) &&
- ((XToolkit.saved_error == null) ||
- (XToolkit.saved_error.get_error_code() == XConstants.Success)))
+ ((XErrorHandlerUtil.saved_error == null) ||
+ (XErrorHandlerUtil.saved_error.get_error_code() == XConstants.Success)))
{
return wattr.get_map_state();
}
--- a/jdk/src/solaris/classes/sun/awt/X11/generator/WrapperGenerator.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/generator/WrapperGenerator.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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
@@ -996,7 +996,7 @@
pw.println("\t\t\t}");
pw.println("\t\t\t__executed = true;");
pw.println("\t\t\tif (errorHandler != null) {");
- pw.println("\t\t\t XToolkit.WITH_XERROR_HANDLER(errorHandler);");
+ pw.println("\t\t\t XErrorHandlerUtil.WITH_XERROR_HANDLER(errorHandler);");
pw.println("\t\t\t}");
iter = ft.getArguments().iterator();
while (iter.hasNext()) {
@@ -1025,7 +1025,7 @@
}
pw.println("\t\t\t);");
pw.println("\t\t\tif (errorHandler != null) {");
- pw.println("\t\t\t XToolkit.RESTORE_XERROR_HANDLER();");
+ pw.println("\t\t\t XErrorHandlerUtil.RESTORE_XERROR_HANDLER();");
pw.println("\t\t\t}");
if (!ft.isVoid()) {
pw.println("\t\t\treturn status;");
--- a/jdk/src/solaris/classes/sun/print/IPPPrintService.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/solaris/classes/sun/print/IPPPrintService.java Mon Jun 03 23:23:20 2013 -0700
@@ -1023,6 +1023,13 @@
// this is already supported in UnixPrintJob
catList.add(Destination.class);
+
+ // It is unfortunate that CUPS doesn't provide a way to query
+ // if printer supports collation but since most printers
+ // now supports collation and that most OS has a way
+ // of setting it, it is a safe assumption to just always
+ // include SheetCollate as supported attribute.
+ catList.add(SheetCollate.class);
}
// With the assumption that Chromaticity is equivalent to
--- a/jdk/src/solaris/native/sun/awt/awt_GraphicsEnv.c Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/solaris/native/sun/awt/awt_GraphicsEnv.c Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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
@@ -758,6 +758,8 @@
}
XSetIOErrorHandler(xioerror_handler);
+ JNU_CallStaticMethodByName(env, NULL, "sun/awt/X11/XErrorHandlerUtil", "init", "(J)V",
+ ptr_to_jlong(awt_display));
/* set awt_numScreens, and whether or not we're using Xinerama */
xineramaInit();
@@ -904,28 +906,12 @@
static jint canUseShmExt = UNSET_MITSHM;
static jint canUseShmExtPixmaps = UNSET_MITSHM;
-static jboolean xshmAttachFailed = JNI_FALSE;
-
-int J2DXErrHandler(Display *display, XErrorEvent *xerr) {
- int ret = 0;
- if (xerr->minor_code == X_ShmAttach) {
- xshmAttachFailed = JNI_TRUE;
- } else {
- ret = (*xerror_saved_handler)(display, xerr);
- }
- return ret;
-}
-jboolean isXShmAttachFailed() {
- return xshmAttachFailed;
-}
-void resetXShmAttachFailed() {
- xshmAttachFailed = JNI_FALSE;
-}
void TryInitMITShm(JNIEnv *env, jint *shmExt, jint *shmPixmaps) {
XShmSegmentInfo shminfo;
int XShmMajor, XShmMinor;
int a, b, c;
+ jboolean xShmAttachResult;
AWT_LOCK();
if (canUseShmExt != UNSET_MITSHM) {
@@ -963,21 +949,14 @@
}
shminfo.readOnly = True;
- resetXShmAttachFailed();
- /**
- * The J2DXErrHandler handler will set xshmAttachFailed
- * to JNI_TRUE if any Shm error has occured.
- */
- EXEC_WITH_XERROR_HANDLER(J2DXErrHandler,
- XShmAttach(awt_display, &shminfo));
-
+ xShmAttachResult = TryXShmAttach(env, awt_display, &shminfo);
/**
* Get rid of the id now to reduce chances of leaking
* system resources.
*/
shmctl(shminfo.shmid, IPC_RMID, 0);
- if (isXShmAttachFailed() == JNI_FALSE) {
+ if (xShmAttachResult == JNI_TRUE) {
canUseShmExt = CAN_USE_MITSHM;
/* check if we can use shared pixmaps */
XShmQueryVersion(awt_display, &XShmMajor, &XShmMinor,
@@ -992,6 +971,23 @@
}
AWT_UNLOCK();
}
+
+/*
+ * Must be called with the acquired AWT lock.
+ */
+jboolean TryXShmAttach(JNIEnv *env, Display *display, XShmSegmentInfo *shminfo) {
+ jboolean errorOccurredFlag = JNI_FALSE;
+ jobject errorHandlerRef;
+
+ /*
+ * XShmAttachHandler will set its internal flag to JNI_TRUE, if any Shm error occurs.
+ */
+ EXEC_WITH_XERROR_HANDLER(env, "sun/awt/X11/XErrorHandler$XShmAttachHandler",
+ "()Lsun/awt/X11/XErrorHandler$XShmAttachHandler;", JNI_TRUE,
+ errorHandlerRef, errorOccurredFlag,
+ XShmAttach(display, shminfo));
+ return errorOccurredFlag == JNI_FALSE ? JNI_TRUE : JNI_FALSE;
+}
#endif /* MITSHM */
/*
--- a/jdk/src/solaris/native/sun/awt/awt_GraphicsEnv.h Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/solaris/native/sun/awt/awt_GraphicsEnv.h Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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
@@ -50,8 +50,7 @@
extern int XShmQueryExtension();
void TryInitMITShm(JNIEnv *env, jint *shmExt, jint *shmPixmaps);
-void resetXShmAttachFailed();
-jboolean isXShmAttachFailed();
+jboolean TryXShmAttach(JNIEnv *env, Display *display, XShmSegmentInfo *shminfo);
#endif /* MITSHM */
--- a/jdk/src/solaris/native/sun/awt/awt_util.c Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/solaris/native/sun/awt/awt_util.c Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2013, Oracle and/or its affiliates. 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
@@ -41,18 +41,6 @@
#include "java_awt_event_MouseWheelEvent.h"
-/*
- * Since X reports protocol errors asynchronously, we often need to
- * install an error handler that acts like a callback. While that
- * specialized handler is installed we save original handler here.
- */
-XErrorHandler xerror_saved_handler;
-
-/*
- * A place for error handler to report the error code.
- */
-unsigned char xerror_code;
-
extern jint getModifiers(uint32_t state, jint button, jint keyCode);
extern jint getButton(uint32_t button);
--- a/jdk/src/solaris/native/sun/awt/awt_util.h Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/solaris/native/sun/awt/awt_util.h Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2013, Oracle and/or its affiliates. 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,42 +29,47 @@
#ifndef HEADLESS
#include "gdefs.h"
-#define WITH_XERROR_HANDLER(f) do { \
- XSync(awt_display, False); \
- xerror_code = Success; \
- xerror_saved_handler = XSetErrorHandler(f); \
-} while (0)
-
-/* Convenience macro for handlers to use */
-#define XERROR_SAVE(err) do { \
- xerror_code = (err)->error_code; \
-} while (0)
-
-#define RESTORE_XERROR_HANDLER do { \
- XSync(awt_display, False); \
- XSetErrorHandler(xerror_saved_handler); \
-} while (0)
-
-#define EXEC_WITH_XERROR_HANDLER(f, code) do { \
- WITH_XERROR_HANDLER(f); \
- do { \
- code; \
- } while (0); \
- RESTORE_XERROR_HANDLER; \
+/*
+ * Expected types of arguments of the macro.
+ * (JNIEnv*, const char*, const char*, jboolean, jobject)
+ */
+#define WITH_XERROR_HANDLER(env, handlerClassName, getInstanceSignature, \
+ handlerHasFlag, handlerRef) do { \
+ handlerRef = JNU_CallStaticMethodByName(env, NULL, handlerClassName, "getInstance", \
+ getInstanceSignature).l; \
+ if (handlerHasFlag == JNI_TRUE) { \
+ JNU_CallMethodByName(env, NULL, handlerRef, "setErrorOccurredFlag", "(Z)V", JNI_FALSE); \
+ } \
+ JNU_CallStaticMethodByName(env, NULL, "sun/awt/X11/XErrorHandlerUtil", "WITH_XERROR_HANDLER", \
+ "(Lsun/awt/X11/XErrorHandler;)V", handlerRef); \
} while (0)
/*
- * Since X reports protocol errors asynchronously, we often need to
- * install an error handler that acts like a callback. While that
- * specialized handler is installed we save original handler here.
+ * Expected types of arguments of the macro.
+ * (JNIEnv*)
*/
-extern XErrorHandler xerror_saved_handler;
+#define RESTORE_XERROR_HANDLER(env) do { \
+ JNU_CallStaticMethodByName(env, NULL, "sun/awt/X11/XErrorHandlerUtil", \
+ "RESTORE_XERROR_HANDLER", "()V"); \
+} while (0)
/*
- * A place for error handler to report the error code.
+ * Expected types of arguments of the macro.
+ * (JNIEnv*, const char*, const char*, jboolean, jobject, jboolean, No type - C expression)
*/
-extern unsigned char xerror_code;
-
+#define EXEC_WITH_XERROR_HANDLER(env, handlerClassName, getInstanceSignature, handlerHasFlag, \
+ handlerRef, errorOccurredFlag, code) do { \
+ handlerRef = NULL; \
+ WITH_XERROR_HANDLER(env, handlerClassName, getInstanceSignature, handlerHasFlag, handlerRef); \
+ do { \
+ code; \
+ } while (0); \
+ RESTORE_XERROR_HANDLER(env); \
+ if (handlerHasFlag == JNI_TRUE) { \
+ errorOccurredFlag = JNU_CallMethodByName(env, NULL, handlerRef, "getErrorOccurredFlag", \
+ "()Z").z; \
+ } \
+} while (0)
#endif /* !HEADLESS */
#ifndef INTERSECTS
--- a/jdk/src/solaris/native/sun/java2d/opengl/GLXSurfaceData.c Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/solaris/native/sun/java2d/opengl/GLXSurfaceData.c Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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
@@ -48,8 +48,6 @@
extern void
OGLSD_SetNativeDimensions(JNIEnv *env, OGLSDOps *oglsdo, jint w, jint h);
-jboolean surfaceCreationFailed = JNI_FALSE;
-
#endif /* !HEADLESS */
JNIEXPORT void JNICALL
@@ -349,18 +347,6 @@
return JNI_TRUE;
}
-static int
-GLXSD_BadAllocXErrHandler(Display *display, XErrorEvent *xerr)
-{
- int ret = 0;
- if (xerr->error_code == BadAlloc) {
- surfaceCreationFailed = JNI_TRUE;
- } else {
- ret = (*xerror_saved_handler)(display, xerr);
- }
- return ret;
-}
-
JNIEXPORT jboolean JNICALL
Java_sun_java2d_opengl_GLXSurfaceData_initPbuffer
(JNIEnv *env, jobject glxsd,
@@ -376,6 +362,8 @@
int attrlist[] = {GLX_PBUFFER_WIDTH, 0,
GLX_PBUFFER_HEIGHT, 0,
GLX_PRESERVED_CONTENTS, GL_FALSE, 0};
+ jboolean errorOccurredFlag;
+ jobject errorHandlerRef;
J2dTraceLn3(J2D_TRACE_INFO,
"GLXSurfaceData_initPbuffer: w=%d h=%d opq=%d",
@@ -403,12 +391,13 @@
attrlist[1] = width;
attrlist[3] = height;
- surfaceCreationFailed = JNI_FALSE;
- EXEC_WITH_XERROR_HANDLER(
- GLXSD_BadAllocXErrHandler,
- pbuffer = j2d_glXCreatePbuffer(awt_display,
- glxinfo->fbconfig, attrlist));
- if ((pbuffer == 0) || surfaceCreationFailed) {
+ errorOccurredFlag = JNI_FALSE;
+ EXEC_WITH_XERROR_HANDLER(env, "sun/awt/X11/XErrorHandler$GLXBadAllocHandler",
+ "()Lsun/awt/X11/XErrorHandler$GLXBadAllocHandler;", JNI_TRUE,
+ errorHandlerRef, errorOccurredFlag,
+ pbuffer = j2d_glXCreatePbuffer(awt_display, glxinfo->fbconfig, attrlist));
+
+ if ((pbuffer == 0) || errorOccurredFlag) {
J2dRlsTraceLn(J2D_TRACE_ERROR,
"GLXSurfaceData_initPbuffer: could not create glx pbuffer");
return JNI_FALSE;
--- a/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2013, Oracle and/or its affiliates. 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
@@ -65,7 +65,6 @@
static DisposeFunc X11SD_Dispose;
static GetPixmapBgFunc X11SD_GetPixmapWithBg;
static ReleasePixmapBgFunc X11SD_ReleasePixmapWithBg;
-extern int J2DXErrHandler(Display *display, XErrorEvent *xerr);
extern AwtGraphicsConfigDataPtr
getGraphicsConfigFromComponentPeer(JNIEnv *env, jobject this);
extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs;
@@ -521,6 +520,8 @@
{
XImage *img = NULL;
XShmSegmentInfo *shminfo;
+ JNIEnv* env;
+ jboolean xShmAttachResult;
shminfo = malloc(sizeof(XShmSegmentInfo));
if (shminfo == NULL) {
@@ -559,9 +560,8 @@
shminfo->readOnly = False;
- resetXShmAttachFailed();
- EXEC_WITH_XERROR_HANDLER(J2DXErrHandler,
- XShmAttach(awt_display, shminfo));
+ env = (JNIEnv*)JNU_GetEnv(jvm, JNI_VERSION_1_2);
+ xShmAttachResult = TryXShmAttach(env, awt_display, shminfo);
/*
* Once the XSync round trip has finished then we
@@ -570,7 +570,7 @@
*/
shmctl(shminfo->shmid, IPC_RMID, 0);
- if (isXShmAttachFailed() == JNI_TRUE) {
+ if (xShmAttachResult == JNI_FALSE) {
J2dRlsTraceLn1(J2D_TRACE_ERROR,
"X11SD_SetupSharedSegment XShmAttach has failed: %s",
strerror(errno));
--- a/jdk/src/solaris/native/sun/xawt/XlibWrapper.c Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/solaris/native/sun/xawt/XlibWrapper.c Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2013, Oracle and/or its affiliates. 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
@@ -1264,8 +1264,8 @@
if (jvm != NULL) {
env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
if (env) {
- return JNU_CallStaticMethodByName(env, NULL, "sun/awt/X11/XToolkit", "globalErrorHandler", "(JJ)I",
- ptr_to_jlong(dpy), ptr_to_jlong(event)).i;
+ return JNU_CallStaticMethodByName(env, NULL, "sun/awt/X11/XErrorHandlerUtil",
+ "globalErrorHandler", "(JJ)I", ptr_to_jlong(dpy), ptr_to_jlong(event)).i;
}
}
return 0;
--- a/jdk/src/windows/bin/cmdtoargs.c Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/windows/bin/cmdtoargs.c Mon Jun 03 23:23:20 2013 -0700
@@ -128,7 +128,9 @@
*wildcard = JNI_TRUE;
}
if (prev == '\\') {
- *dest++ = prev;
+ for (i = 0 ; i < slashes ; i++) {
+ *dest++ = prev;
+ }
}
*dest++ = ch;
break;
@@ -184,7 +186,7 @@
argv = (StdArg*) JLI_MemRealloc(argv, (nargs+1) * sizeof(StdArg));
argv[nargs].arg = JLI_StringDup(arg);
argv[nargs].has_wildcard = wildcard;
-
+ *arg = NULL;
nargs++;
} while (src != NULL);
@@ -602,6 +604,14 @@
v->add("d", FALSE);
vectors[i++] = v;
+ v= new Vector(argv[0], "\\\\?");
+ v->add("\\\\?", TRUE);
+ vectors[i++] = v;
+
+ v= new Vector(argv[0], "\\\\*");
+ v->add("\\\\*", TRUE);
+ vectors[i++] = v;
+
dotest(vectors);
printf("All tests pass [%d]\n", i);
doexit(0);
--- a/jdk/src/windows/classes/sun/awt/windows/WPathGraphics.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/windows/classes/sun/awt/windows/WPathGraphics.java Mon Jun 03 23:23:20 2013 -0700
@@ -549,6 +549,8 @@
userx += xAdvance;
userpos.x += xAdvance;
deviceTransform.transform(userpos, devpos);
+ devx = devpos.x;
+ devy = devpos.y;
}
} else {
super.drawString(str, x, y, font, frc, targetW);
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java Mon Jun 03 23:23:20 2013 -0700
@@ -100,6 +100,7 @@
public static final int ERROR_INVALID_LEVEL = 124;
public static final int ERROR_DIR_NOT_EMPTY = 145;
public static final int ERROR_ALREADY_EXISTS = 183;
+ public static final int ERROR_MORE_DATA = 234;
public static final int ERROR_DIRECTORY = 267;
public static final int ERROR_NOTIFY_ENUM_DIR = 1022;
public static final int ERROR_NONE_MAPPED = 1332;
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java Mon Jun 03 23:23:20 2013 -0700
@@ -973,19 +973,19 @@
* HANDLE CreateIoCompletionPort (
* HANDLE FileHandle,
* HANDLE ExistingCompletionPort,
- * DWORD CompletionKey,
+ * ULONG_PTR CompletionKey,
* DWORD NumberOfConcurrentThreads
* )
*/
static native long CreateIoCompletionPort(long fileHandle, long existingPort,
- int completionKey) throws WindowsException;
+ long completionKey) throws WindowsException;
/**
* GetQueuedCompletionStatus(
* HANDLE CompletionPort,
* LPDWORD lpNumberOfBytesTransferred,
- * LPDWORD lpCompletionKey,
+ * PULONG_PTR lpCompletionKey,
* LPOVERLAPPED *lpOverlapped,
* DWORD dwMilliseconds
*/
@@ -999,12 +999,12 @@
static class CompletionStatus {
private int error;
private int bytesTransferred;
- private int completionKey;
+ private long completionKey;
private CompletionStatus() { }
int error() { return error; }
int bytesTransferred() { return bytesTransferred; }
- int completionKey() { return completionKey; }
+ long completionKey() { return completionKey; }
}
private static native void GetQueuedCompletionStatus0(long completionPort,
CompletionStatus status) throws WindowsException;
@@ -1013,12 +1013,12 @@
* PostQueuedCompletionStatus(
* HANDLE CompletionPort,
* DWORD dwNumberOfBytesTransferred,
- * DWORD dwCompletionKey,
+ * ULONG_PTR dwCompletionKey,
* LPOVERLAPPED lpOverlapped
* )
*/
static native void PostQueuedCompletionStatus(long completionPort,
- int completionKey) throws WindowsException;
+ long completionKey) throws WindowsException;
/**
* ReadDirectoryChangesW(
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsWatchService.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsWatchService.java Mon Jun 03 23:23:20 2013 -0700
@@ -41,6 +41,7 @@
class WindowsWatchService
extends AbstractWatchService
{
+ private final static int WAKEUP_COMPLETION_KEY = 0;
private final Unsafe unsafe = Unsafe.getUnsafe();
// background thread to service I/O completion port
@@ -83,7 +84,7 @@
*/
private class WindowsWatchKey extends AbstractWatchKey {
// file key (used to detect existing registrations)
- private FileKey fileKey;
+ private final FileKey fileKey;
// handle to directory
private volatile long handle = INVALID_HANDLE_VALUE;
@@ -223,8 +224,7 @@
FileKey other = (FileKey)obj;
if (this.volSerialNumber != other.volSerialNumber) return false;
if (this.fileIndexHigh != other.fileIndexHigh) return false;
- if (this.fileIndexLow != other.fileIndexLow) return false;
- return true;
+ return this.fileIndexLow == other.fileIndexLow;
}
}
@@ -268,6 +268,7 @@
private static final short OFFSETOF_FILENAME = 12;
// size of per-directory buffer for events (FIXME - make this configurable)
+ // Need to be less than 4*16384 = 65536. DWORD align.
private static final int CHANGES_BUFFER_SIZE = 16 * 1024;
private final WindowsFileSystem fs;
@@ -275,27 +276,28 @@
private final long port;
// maps completion key to WatchKey
- private final Map<Integer,WindowsWatchKey> int2key;
+ private final Map<Integer,WindowsWatchKey> ck2key;
// maps file key to WatchKey
private final Map<FileKey,WindowsWatchKey> fk2key;
// unique completion key for each directory
+ // native completion key capacity is 64 bits on Win64.
private int lastCompletionKey;
Poller(WindowsFileSystem fs, WindowsWatchService watcher, long port) {
this.fs = fs;
this.watcher = watcher;
this.port = port;
- this.int2key = new HashMap<Integer,WindowsWatchKey>();
- this.fk2key = new HashMap<FileKey,WindowsWatchKey>();
+ this.ck2key = new HashMap<>();
+ this.fk2key = new HashMap<>();
this.lastCompletionKey = 0;
}
@Override
void wakeup() throws IOException {
try {
- PostQueuedCompletionStatus(port, 0);
+ PostQueuedCompletionStatus(port, WAKEUP_COMPLETION_KEY);
} catch (WindowsException x) {
throw new IOException(x.getMessage());
}
@@ -322,7 +324,6 @@
for (WatchEvent.Modifier modifier: modifiers) {
if (modifier == ExtendedWatchEventModifier.FILE_TREE) {
watchSubtree = true;
- continue;
} else {
if (modifier == null)
return new NullPointerException();
@@ -333,7 +334,7 @@
}
// open directory
- long handle = -1L;
+ long handle;
try {
handle = CreateFile(dir.getPathForWin32Calls(),
FILE_LIST_DIRECTORY,
@@ -347,7 +348,7 @@
boolean registered = false;
try {
// read attributes and check file is a directory
- WindowsFileAttributes attrs = null;
+ WindowsFileAttributes attrs;
try {
attrs = WindowsFileAttributes.readAttributes(handle);
} catch (WindowsException x) {
@@ -370,9 +371,10 @@
return existing;
}
- // unique completion key (skip 0)
+ // Can overflow the int type capacity.
+ // Skip WAKEUP_COMPLETION_KEY value.
int completionKey = ++lastCompletionKey;
- if (completionKey == 0)
+ if (completionKey == WAKEUP_COMPLETION_KEY)
completionKey = ++lastCompletionKey;
// associate handle with completion port
@@ -418,13 +420,13 @@
// 1. remove mapping from old completion key to existing watch key
// 2. release existing key's resources (handle/buffer)
// 3. re-initialize key with new handle/buffer
- int2key.remove(existing.completionKey());
+ ck2key.remove(existing.completionKey());
existing.releaseResources();
watchKey = existing.init(handle, events, watchSubtree, buffer,
countAddress, overlappedAddress, completionKey);
}
// map completion map to watch key
- int2key.put(completionKey, watchKey);
+ ck2key.put(completionKey, watchKey);
registered = true;
return watchKey;
@@ -440,7 +442,7 @@
WindowsWatchKey key = (WindowsWatchKey)obj;
if (key.isValid()) {
fk2key.remove(key.fileKey());
- int2key.remove(key.completionKey());
+ ck2key.remove(key.completionKey());
key.invalidate();
}
}
@@ -449,11 +451,11 @@
@Override
void implCloseAll() {
// cancel all keys
- for (Map.Entry<Integer,WindowsWatchKey> entry: int2key.entrySet()) {
+ for (Map.Entry<Integer, WindowsWatchKey> entry: ck2key.entrySet()) {
entry.getValue().invalidate();
}
fk2key.clear();
- int2key.clear();
+ ck2key.clear();
// close I/O completion port
CloseHandle(port);
@@ -517,7 +519,7 @@
@Override
public void run() {
for (;;) {
- CompletionStatus info = null;
+ CompletionStatus info;
try {
info = GetQueuedCompletionStatus(port);
} catch (WindowsException x) {
@@ -527,7 +529,7 @@
}
// wakeup
- if (info.completionKey() == 0) {
+ if (info.completionKey() == WAKEUP_COMPLETION_KEY) {
boolean shutdown = processRequests();
if (shutdown) {
return;
@@ -536,7 +538,7 @@
}
// map completionKey to get WatchKey
- WindowsWatchKey key = int2key.get(info.completionKey());
+ WindowsWatchKey key = ck2key.get((int)info.completionKey());
if (key == null) {
// We get here when a registration is changed. In that case
// the directory is closed which causes an event with the
@@ -544,38 +546,44 @@
continue;
}
- // ReadDirectoryChangesW failed
- if (info.error() != 0) {
+ boolean criticalError = false;
+ int errorCode = info.error();
+ int messageSize = info.bytesTransferred();
+ if (errorCode == ERROR_NOTIFY_ENUM_DIR) {
// buffer overflow
- if (info.error() == ERROR_NOTIFY_ENUM_DIR) {
- key.signalEvent(StandardWatchEventKinds.OVERFLOW, null);
- } else {
- // other error so cancel key
- implCancelKey(key);
- key.signal();
- }
- continue;
- }
+ key.signalEvent(StandardWatchEventKinds.OVERFLOW, null);
+ } else if (errorCode != 0 && errorCode != ERROR_MORE_DATA) {
+ // ReadDirectoryChangesW failed
+ criticalError = true;
+ } else {
+ // ERROR_MORE_DATA is a warning about incomplite
+ // data transfer over TCP/UDP stack. For the case
+ // [messageSize] is zero in the most of cases.
- // process the events
- if (info.bytesTransferred() > 0) {
- processEvents(key, info.bytesTransferred());
- } else {
- // insufficient buffer size
- key.signalEvent(StandardWatchEventKinds.OVERFLOW, null);
- }
+ if (messageSize > 0) {
+ // process non-empty events.
+ processEvents(key, messageSize);
+ } else if (errorCode == 0) {
+ // insufficient buffer size
+ // not described, but can happen.
+ key.signalEvent(StandardWatchEventKinds.OVERFLOW, null);
+ }
- // start read for next batch of changes
- try {
- ReadDirectoryChangesW(key.handle(),
- key.buffer().address(),
- CHANGES_BUFFER_SIZE,
- key.watchSubtree(),
- ALL_FILE_NOTIFY_EVENTS,
- key.countAddress(),
- key.overlappedAddress());
- } catch (WindowsException x) {
- // no choice but to cancel key
+ // start read for next batch of changes
+ try {
+ ReadDirectoryChangesW(key.handle(),
+ key.buffer().address(),
+ CHANGES_BUFFER_SIZE,
+ key.watchSubtree(),
+ ALL_FILE_NOTIFY_EVENTS,
+ key.countAddress(),
+ key.overlappedAddress());
+ } catch (WindowsException x) {
+ // no choice but to cancel key
+ criticalError = true;
+ }
+ }
+ if (criticalError) {
implCancelKey(key);
key.signal();
}
--- a/jdk/src/windows/classes/sun/security/krb5/internal/tools/Ktab.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/windows/classes/sun/security/krb5/internal/tools/Ktab.java Mon Jun 03 23:23:20 2013 -0700
@@ -80,42 +80,24 @@
} else {
ktab.processArgs(args);
}
- try {
+ ktab.table = KeyTab.getInstance(ktab.name);
+ if (ktab.table.isMissing() && ktab.action != 'a') {
if (ktab.name == null) {
- // ktab.admin = new KeyTabAdmin(); // use the default keytab.
- ktab.table = KeyTab.getInstance();
- if (ktab.table == null) {
- if (ktab.action == 'a') {
- ktab.table = KeyTab.create();
- } else {
- System.out.println("No default key table exists.");
- System.exit(-1);
- }
- }
+ System.out.println("No default key table exists.");
} else {
- if ((ktab.action != 'a') &&
- !(new File(ktab.name)).exists()) {
- System.out.println("Key table " +
- ktab.name + " does not exist.");
- System.exit(-1);
- } else {
- ktab.table = KeyTab.getInstance(ktab.name);
- }
- if (ktab.table == null) {
- if (ktab.action == 'a') {
- ktab.table = KeyTab.create(ktab.name);
- } else {
- System.out.println("The format of key table " +
- ktab.name + " is incorrect.");
- System.exit(-1);
- }
- }
+ System.out.println("Key table " +
+ ktab.name + " does not exist.");
}
- } catch (RealmException e) {
- System.err.println("Error loading key table.");
System.exit(-1);
- } catch (IOException e) {
- System.err.println("Error loading key table.");
+ }
+ if (!ktab.table.isValid()) {
+ if (ktab.name == null) {
+ System.out.println("The format of the default key table " +
+ " is incorrect.");
+ } else {
+ System.out.println("The format of key table " +
+ ktab.name + " is incorrect.");
+ }
System.exit(-1);
}
switch (ktab.action) {
--- a/jdk/src/windows/native/java/io/WinNTFileSystem_md.c Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/windows/native/java/io/WinNTFileSystem_md.c Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. 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
@@ -199,7 +199,7 @@
/**
* If the given attributes are the attributes of a reparse point, then
- * read and return the attributes of the final target.
+ * read and return the attributes of the special cases.
*/
DWORD getFinalAttributesIfReparsePoint(WCHAR *path, DWORD a)
{
@@ -213,6 +213,28 @@
return a;
}
+/**
+ * Take special cases into account when retrieving the attributes
+ * of path
+ */
+DWORD getFinalAttributes(WCHAR *path)
+{
+ DWORD attr = INVALID_FILE_ATTRIBUTES;
+
+ WIN32_FILE_ATTRIBUTE_DATA wfad;
+ WIN32_FIND_DATAW wfd;
+ HANDLE h;
+
+ if (GetFileAttributesExW(path, GetFileExInfoStandard, &wfad)) {
+ attr = getFinalAttributesIfReparsePoint(path, wfad.dwFileAttributes);
+ } else if (GetLastError() == ERROR_SHARING_VIOLATION &&
+ (h = FindFirstFileW(path, &wfd)) != INVALID_HANDLE_VALUE) {
+ attr = getFinalAttributesIfReparsePoint(path, wfd.dwFileAttributes);
+ CloseHandle(h);
+ }
+ return attr;
+}
+
JNIEXPORT jstring JNICALL
Java_java_io_WinNTFileSystem_canonicalize0(JNIEnv *env, jobject this,
jstring pathname)
@@ -337,38 +359,21 @@
Java_java_io_WinNTFileSystem_getBooleanAttributes(JNIEnv *env, jobject this,
jobject file)
{
-
jint rv = 0;
jint pathlen;
- /* both pagefile.sys and hiberfil.sys have length 12 */
-#define SPECIALFILE_NAMELEN 12
-
WCHAR *pathbuf = fileToNTPath(env, file, ids.path);
- WIN32_FILE_ATTRIBUTE_DATA wfad;
if (pathbuf == NULL)
return rv;
if (!isReservedDeviceNameW(pathbuf)) {
- if (GetFileAttributesExW(pathbuf, GetFileExInfoStandard, &wfad)) {
- DWORD a = getFinalAttributesIfReparsePoint(pathbuf, wfad.dwFileAttributes);
- if (a != INVALID_FILE_ATTRIBUTES) {
- rv = (java_io_FileSystem_BA_EXISTS
- | ((a & FILE_ATTRIBUTE_DIRECTORY)
- ? java_io_FileSystem_BA_DIRECTORY
- : java_io_FileSystem_BA_REGULAR)
- | ((a & FILE_ATTRIBUTE_HIDDEN)
- ? java_io_FileSystem_BA_HIDDEN : 0));
- }
- } else { /* pagefile.sys is a special case */
- if (GetLastError() == ERROR_SHARING_VIOLATION) {
- rv = java_io_FileSystem_BA_EXISTS;
- if ((pathlen = (jint)wcslen(pathbuf)) >= SPECIALFILE_NAMELEN &&
- (_wcsicmp(pathbuf + pathlen - SPECIALFILE_NAMELEN,
- L"pagefile.sys") == 0) ||
- (_wcsicmp(pathbuf + pathlen - SPECIALFILE_NAMELEN,
- L"hiberfil.sys") == 0))
- rv |= java_io_FileSystem_BA_REGULAR;
- }
+ DWORD a = getFinalAttributes(pathbuf);
+ if (a != INVALID_FILE_ATTRIBUTES) {
+ rv = (java_io_FileSystem_BA_EXISTS
+ | ((a & FILE_ATTRIBUTE_DIRECTORY)
+ ? java_io_FileSystem_BA_DIRECTORY
+ : java_io_FileSystem_BA_REGULAR)
+ | ((a & FILE_ATTRIBUTE_HIDDEN)
+ ? java_io_FileSystem_BA_HIDDEN : 0));
}
}
free(pathbuf);
--- a/jdk/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c Thu May 30 10:58:21 2013 -0700
+++ b/jdk/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c Mon Jun 03 23:23:20 2013 -0700
@@ -162,7 +162,7 @@
}
completionStatus_error = (*env)->GetFieldID(env, clazz, "error", "I");
completionStatus_bytesTransferred = (*env)->GetFieldID(env, clazz, "bytesTransferred", "I");
- completionStatus_completionKey = (*env)->GetFieldID(env, clazz, "completionKey", "I");
+ completionStatus_completionKey = (*env)->GetFieldID(env, clazz, "completionKey", "J");
clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$BackupResult");
if (clazz == NULL) {
@@ -1169,12 +1169,11 @@
JNIEXPORT jlong JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_CreateIoCompletionPort(JNIEnv* env, jclass this,
- jlong fileHandle, jlong existingPort, jint completionKey)
+ jlong fileHandle, jlong existingPort, jlong completionKey)
{
- ULONG_PTR ck = completionKey;
HANDLE port = CreateIoCompletionPort((HANDLE)jlong_to_ptr(fileHandle),
(HANDLE)jlong_to_ptr(existingPort),
- ck,
+ (ULONG_PTR)completionKey,
0);
if (port == NULL) {
throwWindowsException(env, GetLastError());
@@ -1203,21 +1202,20 @@
(*env)->SetIntField(env, obj, completionStatus_error, ioResult);
(*env)->SetIntField(env, obj, completionStatus_bytesTransferred,
(jint)bytesTransferred);
- (*env)->SetIntField(env, obj, completionStatus_completionKey,
- (jint)completionKey);
-
+ (*env)->SetLongField(env, obj, completionStatus_completionKey,
+ (jlong)completionKey);
}
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_PostQueuedCompletionStatus(JNIEnv* env, jclass this,
- jlong completionPort, jint completionKey)
+ jlong completionPort, jlong completionKey)
{
BOOL res;
res = PostQueuedCompletionStatus((HANDLE)jlong_to_ptr(completionPort),
(DWORD)0, /* dwNumberOfBytesTransferred */
- (DWORD)completionKey,
+ (ULONG_PTR)completionKey,
NULL); /* lpOverlapped */
if (res == 0) {
throwWindowsException(env, GetLastError());
@@ -1232,7 +1230,17 @@
BOOL res;
BOOL subtree = (watchSubTree == JNI_TRUE) ? TRUE : FALSE;
- ((LPOVERLAPPED)jlong_to_ptr(pOverlapped))->hEvent = NULL;
+ /* Any unused members of [OVERLAPPED] structure should always be initialized to zero
+ before the structure is used in a function call.
+ Otherwise, the function may fail and return ERROR_INVALID_PARAMETER.
+ http://msdn.microsoft.com/en-us/library/windows/desktop/ms684342%28v=vs.85%29.aspx
+
+ The [Offset] and [OffsetHigh] members of this structure are not used.
+ http://msdn.microsoft.com/en-us/library/windows/desktop/aa365465%28v=vs.85%29.aspx
+
+ [hEvent] should be zero, other fields are the return values. */
+ ZeroMemory((LPOVERLAPPED)jlong_to_ptr(pOverlapped), sizeof(OVERLAPPED));
+
res = ReadDirectoryChangesW((HANDLE)jlong_to_ptr(hDirectory),
(LPVOID)jlong_to_ptr(bufferAddress),
(DWORD)bufferLength,
--- a/jdk/test/Makefile Thu May 30 10:58:21 2013 -0700
+++ b/jdk/test/Makefile Mon Jun 03 23:23:20 2013 -0700
@@ -657,9 +657,12 @@
# Multiple by 4 the timeout numbers
JTREG_TIMEOUT_OPTION = -timeoutFactor:4
JTREG_BASIC_OPTIONS += $(JTREG_TIMEOUT_OPTION)
-# Boost the max memory for jtreg to avoid gc thrashing
+# Set the max memory for jtreg control vm
JTREG_MEMORY_OPTION = -J-Xmx512m
JTREG_BASIC_OPTIONS += $(JTREG_MEMORY_OPTION)
+# Set the max memory for jtreg target test vms
+JTREG_TESTVM_MEMORY_OPTION = -vmoption:-Xmx512m
+JTREG_TEST_OPTIONS += $(JTREG_TESTVM_MEMORY_OPTION)
# Make sure jtreg exists
$(JTREG): $(JT_HOME)
--- a/jdk/test/ProblemList.txt Thu May 30 10:58:21 2013 -0700
+++ b/jdk/test/ProblemList.txt Mon Jun 03 23:23:20 2013 -0700
@@ -137,15 +137,12 @@
# 8008200
java/lang/Class/asSubclass/BasicUnit.java generic-all
-# 8009552
-vm/verifier/TestStaticIF.java generic-all
-
############################################################################
# jdk_management
# 8010897
-sun/management/HotspotRuntimeMBean/GetSafepointSyncTime.java macosx-all
+sun/management/HotspotRuntimeMBean/GetSafepointSyncTime.java macosx-all
############################################################################
@@ -154,9 +151,6 @@
# 6959636
javax/management/loading/LibraryLoader/LibraryLoaderTest.java windows-all
-# 8005472
-com/sun/jmx/remote/NotificationMarshalVersions/TestSerializationMismatch.sh windows-all
-
############################################################################
# jdk_math
@@ -305,9 +299,6 @@
# 7194428
sun/security/mscapi/ShortRSAKey1024.sh windows-all
-# 8000897, vm crash
-sun/security/provider/DSA/TestAlgParameterGenerator.java generic-all
-
# 7144048, performance issue
sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineDeadlock.java generic-all
@@ -338,12 +329,9 @@
sun/jvmstat/monitor/MonitoredVm/CR6672135.java generic-all
# Tests take too long, on sparcs see 7143279
-tools/pack200/CommandLineTests.java solaris-all, macosx-all
+tools/pack200/CommandLineTests.java solaris-all, macosx-all
tools/pack200/Pack200Test.java solaris-all, macosx-all
-# 7150569
-tools/launcher/UnicodeTest.java macosx-all
-
# 8007410
tools/launcher/FXLauncherTest.java linux-all
--- a/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Client/Client.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Client/Client.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,47 +1,78 @@
-import java.nio.charset.Charset;
-import java.nio.file.FileSystems;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardWatchEventKinds;
-import java.nio.file.WatchEvent;
-import java.nio.file.WatchService;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
import javax.management.MBeanServerConnection;
import javax.management.Notification;
import javax.management.NotificationListener;
import javax.management.ObjectName;
+import javax.management.remote.JMXConnectionNotification;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
public class Client {
- public static void main(String[] argv) throws Exception {
- if (argv.length != 1) throw new IllegalArgumentException("Expecting exactly one jmx url argument");
+ public static void run(String url) throws Exception {
+ final int notifEmittedCnt = 10;
+ final CountDownLatch counter = new CountDownLatch(notifEmittedCnt);
+ final Set<Long> seqSet = Collections.synchronizedSet(new HashSet<Long>());
+ final AtomicBoolean duplNotification = new AtomicBoolean();
- JMXServiceURL serverUrl = new JMXServiceURL(argv[0]);
+ JMXServiceURL serverUrl = new JMXServiceURL(url);
ObjectName name = new ObjectName("test", "foo", "bar");
JMXConnector jmxConnector = JMXConnectorFactory.connect(serverUrl);
System.out.println("client connected");
jmxConnector.addConnectionNotificationListener(new NotificationListener() {
+ @Override
public void handleNotification(Notification notification, Object handback) {
- System.err.println("no!" + notification);
+ System.out.println("connection notification: " + notification);
+ if (!seqSet.add(notification.getSequenceNumber())) {
+ duplNotification.set(true);
+ }
+ if (notification.getType().equals(JMXConnectionNotification.NOTIFS_LOST)) {
+ long lostNotifs = ((Long)((JMXConnectionNotification)notification).getUserData()).longValue();
+ for(int i=0;i<lostNotifs;i++) {
+ counter.countDown();
+ }
+ }
}
}, null, null);
MBeanServerConnection jmxServer = jmxConnector.getMBeanServerConnection();
jmxServer.addNotificationListener(name, new NotificationListener() {
+ @Override
public void handleNotification(Notification notification, Object handback) {
- System.out.println("client got:" + notification);
+ System.out.println("client got: " + notification);
+ if (!seqSet.add(notification.getSequenceNumber())) {
+ duplNotification.set(true);
+ }
+ counter.countDown();
}
}, null, null);
- for(int i=0;i<10;i++) {
- System.out.println("client invoking foo");
+ System.out.println("client invoking foo (" + notifEmittedCnt + " times)");
+ for(int i=0;i<notifEmittedCnt;i++) {
+ System.out.print(".");
jmxServer.invoke(name, "foo", new Object[]{}, new String[]{});
- Thread.sleep(50);
}
-
- System.err.println("happy!");
+ System.out.println();
+ try {
+ System.out.println("waiting for " + notifEmittedCnt + " notifications to arrive");
+ if (!counter.await(30, TimeUnit.SECONDS)) {
+ throw new InterruptedException();
+ }
+ if (duplNotification.get()) {
+ System.out.println("ERROR: received duplicated notifications");
+ throw new Error("received duplicated notifications");
+ }
+ System.out.println("\nshutting down client");
+ } catch (InterruptedException e) {
+ System.out.println("ERROR: notification processing thread interrupted");
+ throw new Error("notification thread interrupted unexpectedly");
+ }
}
}
--- a/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Server/Server.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Server/Server.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,11 +1,6 @@
+import java.io.File;
import java.lang.management.ManagementFactory;
import java.net.BindException;
-import java.nio.charset.Charset;
-import java.nio.file.FileSystem;
-import java.nio.file.FileSystems;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardOpenOption;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.ExportException;
import java.util.Random;
@@ -16,7 +11,7 @@
import javax.management.remote.JMXServiceURL;
public class Server {
- public static void main(String[] argv) throws Exception {
+ public static String start() throws Exception {
int serverPort = 12345;
ObjectName name = new ObjectName("test", "foo", "bar");
MBeanServer jmxServer = ManagementFactory.getPlatformMBeanServer();
@@ -40,7 +35,7 @@
JMXServiceURL serverUrl = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:" + serverPort + "/test");
JMXConnectorServer jmxConnector = JMXConnectorServerFactory.newJMXConnectorServer(serverUrl, null, jmxServer);
jmxConnector.start();
- System.out.println(serverUrl);
- System.err.println("server listening on " + serverUrl);
+
+ return serverUrl.toString();
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/TestSerializationMismatch.java Mon Jun 03 23:23:20 2013 -0700
@@ -0,0 +1,123 @@
+
+import java.io.File;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Arrays;
+
+/**
+ * @test
+ * @summary Tests for the RMI unmarshalling errors not to cause silent failure.
+ * @author Jaroslav Bachorik
+ * @bug 6937053 8005472
+ *
+ * @run clean TestSerializationMismatch
+ * @run main TestSerializationMismatch
+ *
+ */
+public class TestSerializationMismatch {
+ static final String clientDir = "Client";
+ static final String serverDir = "Server";
+ static final String testSrc = System.getProperty("test.src");
+ static final String testSrcDir = testSrc != null ? testSrc : ".";
+ static final String testSrcClientDir = testSrcDir + File.separator + clientDir + File.separator;
+ static final String testSrcServerDir = testSrcDir + File.separator + serverDir + File.separator;
+ static final String testClasses = System.getProperty("test.classes");
+ static final String testClassesDir = testClasses != null ? testClasses : ".";
+ static final String testClassesClientDir = testClassesDir + File.separator + clientDir + File.separator;
+ static final String testClassesServerDir = testClassesDir + File.separator + serverDir + File.separator;
+
+ static final boolean debug = true;
+
+ public static void main(String[] args) throws Exception {
+ setup();
+
+ compileClient();
+ compileServer();
+
+ debug("starting server");
+ String url = startServer();
+ debug("server started and listening on " + url);
+ debug("starting client");
+ startClient(url);
+ }
+
+ static void setup() {
+ debug("setting up the output dirs");
+ cleanupDir(testClassesClientDir);
+ cleanupDir(testClassesServerDir);
+ }
+
+ static void cleanupDir(String path) {
+ debug("cleaning " + path);
+ File dir = new File(path);
+ if (dir.exists()) {
+ for(File src : dir.listFiles()) {
+ boolean rslt = src.delete();
+ debug((rslt == false ? "not " : "") + "deleted " + src);
+ }
+ } else {
+ dir.mkdirs();
+ }
+ }
+
+ static void compileClient() {
+ debug("compiling client");
+ compile("-d" , testClassesClientDir,
+ "-sourcepath", testSrcClientDir,
+ testSrcClientDir + "Client.java",
+ testSrcClientDir + "ConfigKey.java",
+ testSrcClientDir + "TestNotification.java");
+ }
+
+ static void compileServer() {
+ debug("compiling server");
+ compile("-d" , testClassesServerDir,
+ "-sourcepath", testSrcServerDir,
+ testSrcServerDir + "Server.java",
+ testSrcServerDir + "ConfigKey.java",
+ testSrcServerDir + "TestNotification.java",
+ testSrcServerDir + "Ste.java",
+ testSrcServerDir + "SteMBean.java");
+ }
+
+ static String startServer() throws Exception {
+ ClassLoader serverCL = customCL(testClassesServerDir);
+
+ Class serverClz = serverCL.loadClass("Server");
+ Method startMethod = serverClz.getMethod("start");
+ return (String)startMethod.invoke(null);
+ }
+
+ static void startClient(String url) throws Exception {
+ ClassLoader clientCL = customCL(testClassesClientDir);
+
+ Thread.currentThread().setContextClassLoader(clientCL);
+ Class clientClz = clientCL.loadClass("Client");
+ Method runMethod = clientClz.getMethod("run", String.class);
+ runMethod.invoke(null, url);
+ }
+
+ static ClassLoader customCL(String classDir) throws Exception {
+ return new URLClassLoader(
+ new URL[]{
+ new File(classDir).toURI().toURL()
+ },
+ TestSerializationMismatch.class.getClassLoader()
+ );
+ }
+
+ static void debug(Object message) {
+ if (debug) {
+ System.out.println(message);
+ }
+ }
+
+ /* run javac <args> */
+ static void compile(String... args) {
+ debug("Running: javac " + Arrays.toString(args));
+ if (com.sun.tools.javac.Main.compile(args) != 0) {
+ throw new RuntimeException("javac failed: args=" + Arrays.toString(args));
+ }
+ }
+}
--- a/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/TestSerializationMismatch.sh Thu May 30 10:58:21 2013 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-#
-# Copyright (c) 2005, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-#
-# @test
-# @summary Tests for the RMI unmarshalling errors not to cause silent failure.
-# @author Jaroslav Bachorik
-# @bug 6937053
-#
-# @run shell TestSerializationMismatch.sh
-#
-
-#set -x
-
-#Set appropriate jdk
-#
-
-if [ ! -z "${TESTJAVA}" ] ; then
- jdk="$TESTJAVA"
-else
- echo "--Error: TESTJAVA must be defined as the pathname of a jdk to test."
- exit 1
-fi
-
-SERVER_TESTCLASSES=$TESTCLASSES/Server
-CLIENT_TESTCLASSES=$TESTCLASSES/Client
-
-URL_PATH=$SERVER_TESTCLASSES/jmxurl
-
-rm $URL_PATH
-
-mkdir -p $SERVER_TESTCLASSES
-mkdir -p $CLIENT_TESTCLASSES
-
-$TESTJAVA/bin/javac -d $CLIENT_TESTCLASSES $TESTSRC/Client/ConfigKey.java $TESTSRC/Client/TestNotification.java $TESTSRC/Client/Client.java
-$TESTJAVA/bin/javac -d $SERVER_TESTCLASSES $TESTSRC/Server/ConfigKey.java $TESTSRC/Server/TestNotification.java $TESTSRC/Server/SteMBean.java $TESTSRC/Server/Ste.java $TESTSRC/Server/Server.java
-
-startServer()
-{
- ($TESTJAVA/bin/java -classpath $SERVER_TESTCLASSES Server) 1>$URL_PATH &
- SERVER_PID=$!
-}
-
-runClient()
-{
- while true
- do
- [ -f $URL_PATH ] && break
- sleep 2
- done
- read JMXURL < $URL_PATH
-
- HAS_ERRORS=`($TESTJAVA/bin/java -classpath $CLIENT_TESTCLASSES Client $JMXURL) 2>&1 | grep -i "SEVERE: Failed to fetch notification, stopping thread. Error is: java.rmi.UnmarshalException"`
-}
-
-startServer
-
-runClient
-
-sleep 1 # wait for notifications to arrive
-
-kill "$SERVER_PID"
-
-if [ -z "$HAS_ERRORS" ]
-then
- echo "Test PASSED"
- exit 0
-fi
-
-echo "Test FAILED"
-echo $HAS_ERRORS 1>&2
-exit 1
-
--- a/jdk/test/java/awt/WMSpecificTests/Metacity/FullscreenDialogModality.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/test/java/awt/WMSpecificTests/Metacity/FullscreenDialogModality.java Mon Jun 03 23:23:20 2013 -0700
@@ -25,6 +25,8 @@
* @test
* @bug 8012586
* @summary verify that modal dialog will appeared above fullscreen window under Metacity WM.
+ * @library ../../regtesthelpers
+ * @build Util
* @run main FullscreenDialogModality
* @run main/othervm FullscreenDialogModality
* @author vkravets
--- a/jdk/test/java/awt/Window/TranslucentJAppletTest/TranslucentJAppletTest.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/test/java/awt/Window/TranslucentJAppletTest/TranslucentJAppletTest.java Mon Jun 03 23:23:20 2013 -0700
@@ -37,11 +37,12 @@
public class TranslucentJAppletTest {
+ private static volatile GraphicsConfiguration graphicsConfig = null;
private static JFrame frame;
private static volatile boolean paintComponentCalled = false;
private static void initAndShowGUI() {
- frame = new JFrame();
+ frame = new JFrame(graphicsConfig);
JApplet applet = new JApplet();
applet.setBackground(new Color(0, 0, 0, 0));
JPanel panel = new JPanel() {
@@ -66,6 +67,27 @@
{
sun.awt.SunToolkit tk = (sun.awt.SunToolkit)Toolkit.getDefaultToolkit();
+ final GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+ for (GraphicsDevice gd : ge.getScreenDevices()) {
+ if (gd.isWindowTranslucencySupported(
+ GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSLUCENT))
+ {
+ for (GraphicsConfiguration gc : gd.getConfigurations()) {
+ if (gc.isTranslucencyCapable()) {
+ graphicsConfig = gc;
+ break;
+ }
+ }
+ }
+ if (graphicsConfig != null) {
+ break;
+ }
+ }
+ if (graphicsConfig == null) {
+ System.out.println("The system does not support translucency. Consider the test passed.");
+ return;
+ }
+
Robot r = new Robot();
Color color1 = r.getPixelColor(100, 100); // (0, 0) in frame coordinates
--- a/jdk/test/java/awt/print/PrinterJob/Collate2DPrintingTest.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/test/java/awt/print/PrinterJob/Collate2DPrintingTest.java Mon Jun 03 23:23:20 2013 -0700
@@ -23,7 +23,7 @@
/**
* @test
- * @bug 6362683
+ * @bug 6362683 8012381
* @summary Collation should work.
* @run main/manual Collate2DPrintingTest
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/print/PrinterJob/PrintLatinCJKTest.java Mon Jun 03 23:23:20 2013 -0700
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 800535
+ * @summary JDK7 Printing: CJK and Latin Text in string overlap
+ * @run main/manual=yesno PrintLatinCJKTest
+ */
+
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.print.PageFormat;
+import java.awt.print.Pageable;
+import java.awt.print.Printable;
+import java.awt.print.PrinterException;
+import java.awt.print.PrinterJob;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JTextArea;
+
+import javax.swing.SwingUtilities;
+
+public class PrintLatinCJKTest implements Printable, ActionListener {
+
+ static PrintLatinCJKTest testInstance = new PrintLatinCJKTest();
+ private PageFormat pf;
+
+ static String info =
+ "You need a printer for this test. If you have none, let "+
+ "the test pass. If there is a printer, press Print, send "+
+ "the output to the printer, and examine it. It should have "+
+ "text looking like this : \u4e00\u4e01\u4e02\u4e03\u4e04English.";
+
+ public static void showFrame() {
+ JFrame f = new JFrame();
+ JTextArea jta = new JTextArea(info, 4, 30);
+ jta.setLineWrap(true);
+ jta.setWrapStyleWord(true);
+ f.add("Center", jta);
+ JButton b = new JButton("Print");
+ b.addActionListener(testInstance);
+ f.add("South", b);
+ f.pack();
+ f.setVisible(true);
+ }
+
+ public int print(Graphics g, PageFormat pf, int pageIndex)
+ throws PrinterException {
+
+ if (pageIndex > 0) {
+ return Printable.NO_SUCH_PAGE;
+ }
+ g.translate((int) pf.getImageableX(), (int) pf.getImageableY());
+ g.setFont(new Font("Dialog", Font.PLAIN, 36));
+ g.drawString("\u4e00\u4e01\u4e02\u4e03\u4e04English", 20, 100);
+ return Printable.PAGE_EXISTS;
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ try {
+ PrinterJob job = PrinterJob.getPrinterJob();
+ job.setPrintable(testInstance);
+ if (job.printDialog()) {
+ job.print();
+ }
+ } catch (PrinterException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ public static void main(String[] args) {
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ showFrame();
+ }
+ });
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/XMLEncoder/Test8013416.java Mon Jun 03 23:23:20 2013 -0700
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8013416
+ * @summary Tests public synthetic methods
+ * @author Sergey Malenkov
+ */
+
+import java.beans.DefaultPersistenceDelegate;
+import java.beans.Encoder;
+import java.beans.Expression;
+import java.beans.Statement;
+import java.beans.XMLEncoder;
+import java.util.HashMap;
+import java.util.Map.Entry;
+import java.util.Set;
+
+public class Test8013416 extends AbstractTest {
+ public static void main(String[] args) {
+ new Test8013416().test(true);
+ }
+
+ protected Object getObject() {
+ Public<String, String> map = new Public<String, String>();
+ map.put(" pz1 ", " pz2 ");
+ map.put(" pz3 ", " pz4 ");
+ return map;
+ }
+
+ @Override
+ protected void initialize(XMLEncoder encoder) {
+ super.initialize(encoder);
+ encoder.setPersistenceDelegate(Public.class, new PublicPersistenceDelegate());
+ }
+
+ private static final class PublicPersistenceDelegate extends DefaultPersistenceDelegate {
+ @Override
+ protected Expression instantiate(Object oldInstance, Encoder out) {
+ return new Expression(oldInstance, oldInstance.getClass(), "new", null);
+ }
+
+ @Override
+ protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
+ super.initialize(type, oldInstance, newInstance, out);
+
+ Public<String, String> map = (Public) oldInstance;
+ for (Entry<String, String> entry : map.getAll()) {
+ String[] args = {entry.getKey(), entry.getValue()};
+ out.writeStatement(new Statement(oldInstance, "put", args));
+ }
+ }
+ }
+
+ public static final class Public<K, V> extends Private<K, V> {
+ }
+
+ private static class Private<K, V> {
+ private HashMap<K, V> map = new HashMap<K, V>();
+
+ public void put(K key, V value) {
+ this.map.put(key, value);
+ }
+
+ public Set<Entry<K, V>> getAll() {
+ return this.map.entrySet();
+ }
+ }
+}
--- a/jdk/test/java/io/File/IsHidden.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/test/java/io/File/IsHidden.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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
@@ -46,6 +46,11 @@
Files.getFileAttributeView(f.toPath(), DosFileAttributeView.class).setHidden(value);
}
+ private static void checkHidden(File f) {
+ if (!f.isHidden())
+ throw new RuntimeException(f + " should be hidden");
+ }
+
private static void testWin32() throws Exception {
File f = new File(dir, "test");
f.deleteOnExit();
@@ -58,6 +63,11 @@
}
ck(".foo", false);
ck("foo", false);
+
+ File pagefile = new File("C:\\pagefile.sys");
+ File hiberfil = new File("C:\\hiberfil.sys");
+ if (pagefile.exists()) checkHidden(pagefile);
+ if (hiberfil.exists()) checkHidden(hiberfil);
}
private static void testUnix() throws Exception {
--- a/jdk/test/java/io/FileInputStream/LargeFileAvailable.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/test/java/io/FileInputStream/LargeFileAvailable.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. 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,7 +23,7 @@
/*
* @test
- * @bug 6402006 7030573
+ * @bug 6402006 7030573 8011136
* @summary Test if available returns correct value when reading
* a large file.
*/
@@ -61,9 +61,12 @@
remaining -= skipBytes(fis, bigSkip, remaining);
remaining -= skipBytes(fis, 10L, remaining);
remaining -= skipBytes(fis, bigSkip, remaining);
- if (fis.available() != (int) remaining) {
- throw new RuntimeException("available() returns "
- + fis.available() + " but expected " + remaining);
+ int expected = (remaining >= Integer.MAX_VALUE)
+ ? Integer.MAX_VALUE
+ : (remaining > 0 ? (int) remaining : 0);
+ if (fis.available() != expected) {
+ throw new RuntimeException("available() returns "
+ + fis.available() + " but expected " + expected);
}
} finally {
file.delete();
@@ -77,19 +80,18 @@
long skip = is.skip(toSkip);
if (skip != toSkip) {
throw new RuntimeException("skip() returns " + skip
- + " but expected " + toSkip);
+ + " but expected " + toSkip);
}
long remaining = avail - skip;
- int expected = remaining >= Integer.MAX_VALUE
- ? Integer.MAX_VALUE
- : (int) remaining;
+ int expected = (remaining >= Integer.MAX_VALUE)
+ ? Integer.MAX_VALUE
+ : (remaining > 0 ? (int) remaining : 0);
- System.out.println("Skipped " + skip + " bytes "
- + " available() returns " + expected +
- " remaining=" + remaining);
+ System.out.println("Skipped " + skip + " bytes, available() returns "
+ + expected + ", remaining " + remaining);
if (is.available() != expected) {
throw new RuntimeException("available() returns "
- + is.available() + " but expected " + expected);
+ + is.available() + " but expected " + expected);
}
return skip;
}
--- a/jdk/test/java/io/FileInputStream/NegativeAvailable.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/test/java/io/FileInputStream/NegativeAvailable.java Mon Jun 03 23:23:20 2013 -0700
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8010837
+ * @bug 8010837 8011136
* @summary Test if available returns correct value when skipping beyond
* the end of a file.
* @author Dan Xu
@@ -42,6 +42,7 @@
public static void main(String[] args) throws IOException {
final int SIZE = 10;
final int SKIP = 5;
+ final int NEGATIVE_SKIP = -5;
// Create a temporary file with size of 10 bytes.
Path tmp = Files.createTempFile(null, null);
@@ -56,12 +57,15 @@
try (FileInputStream fis = new FileInputStream(tempFile)) {
if (tempFile.length() != SIZE) {
throw new RuntimeException("unexpected file size = "
- + tempFile.length());
+ + tempFile.length());
}
long space = skipBytes(fis, SKIP, SIZE);
+ space = skipBytes(fis, NEGATIVE_SKIP, space);
space = skipBytes(fis, SKIP, space);
space = skipBytes(fis, SKIP, space);
space = skipBytes(fis, SKIP, space);
+ space = skipBytes(fis, NEGATIVE_SKIP, space);
+ space = skipBytes(fis, NEGATIVE_SKIP, space);
}
Files.deleteIfExists(tmp);
}
@@ -74,17 +78,18 @@
long skip = fis.skip(toSkip);
if (skip != toSkip) {
throw new RuntimeException("skip() returns " + skip
- + " but expected " + toSkip);
+ + " but expected " + toSkip);
}
- long remaining = space - toSkip;
+ long newSpace = space - toSkip;
+ long remaining = newSpace > 0 ? newSpace : 0;
int avail = fis.available();
if (avail != remaining) {
throw new RuntimeException("available() returns " + avail
- + " but expected " + remaining);
+ + " but expected " + remaining);
}
System.out.println("Skipped " + skip + " bytes "
- + " available() returns " + avail);
- return remaining;
+ + " available() returns " + avail);
+ return newSpace;
}
}
--- a/jdk/test/java/io/pathNames/General.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/test/java/io/pathNames/General.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2000, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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
@@ -40,7 +40,7 @@
/* Generate a filename unique to this run */
- private static String gensym() {
+ protected static String gensym() {
return "x." + ++gensymCounter;
}
@@ -127,9 +127,9 @@
}
for (int i = 0; i < dl.length; i++) {
File f = new File(d, dl[i]);
- if (f.isDirectory() && f.canRead()) {
+ if (f.isDirectory()) {
String[] dl2 = f.list();
- if (dl2.length >= 250) {
+ if (dl2 == null || dl2.length >= 250) {
/* Heuristic to avoid scanning huge directories */
continue;
}
@@ -277,8 +277,8 @@
{
check(ans, ask + slash);
checkNames(depth, create,
- ans.endsWith(File.separator) ? ans : ans + File.separator,
- ask + slash);
+ ans,
+ ask);
}
@@ -308,13 +308,16 @@
String ans, String ask)
throws Exception
{
+ ans = ans.endsWith(File.separator) ? ans : ans + File.separator;
+ ask = ask.endsWith(File.separator) ? ask : ask + File.separator;
+
int d = depth - 1;
File f = new File(ans);
String n;
/* Normal name */
if (f.exists()) {
- if (f.isDirectory() && f.canRead()) {
+ if (f.isDirectory() && f.list() != null) {
if ((n = findSomeFile(ans, create)) != null)
checkSlashes(d, create, ans + n, ask + n);
if ((n = findSomeDir(ans, create)) != null)
--- a/jdk/test/java/io/pathNames/GeneralWin32.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/test/java/io/pathNames/GeneralWin32.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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
@@ -22,7 +22,7 @@
*/
/* @test
- @bug 4032066 4039597 4046914 4054511 4065189 4109131 4875229 6983520
+ @bug 4032066 4039597 4046914 4054511 4065189 4109131 4875229 6983520 8009258
@summary General exhaustive test of win32 pathname handling
@author Mark Reinhold
@@ -31,8 +31,6 @@
*/
import java.io.*;
-import java.util.*;
-
public class GeneralWin32 extends General {
@@ -49,25 +47,29 @@
private static final String EXISTENT_UNC_SHARE = "pcdist";
private static final String NONEXISTENT_UNC_HOST = "non-existent-unc-host";
private static final String NONEXISTENT_UNC_SHARE = "bogus-share";
-
+ private static final int DEPTH = 2;
+ private static String baseDir = null;
+ private static String userDir = null;
/* Pathnames relative to working directory */
- private static void checkCaseLookup(String ud) throws IOException {
+ private static void checkCaseLookup() throws IOException {
/* Use long names here to avoid 8.3 format, which Samba servers often
force to lowercase */
- File d = new File("XyZzY0123", "FOO_bar_BAZ");
- File f = new File(d, "GLORPified");
+ String relative = baseDir.substring(userDir.length() + 1);
+ File d1 = new File(relative, "XyZzY0123");
+ File d2 = new File(d1, "FOO_bar_BAZ");
+ File f = new File(d2, "GLORPified");
if (!f.exists()) {
- if (!d.exists()) {
- if (!d.mkdirs()) {
- throw new RuntimeException("Can't create directory " + d);
+ if (!d2.exists()) {
+ if (!d2.mkdirs()) {
+ throw new RuntimeException("Can't create directory " + d2);
}
}
OutputStream o = new FileOutputStream(f);
o.close();
}
- File f2 = new File(d.getParent(), "mumble"); /* For later ud tests */
+ File f2 = new File(d2.getParent(), "mumble"); /* For later ud tests */
if (!f2.exists()) {
OutputStream o = new FileOutputStream(f2);
o.close();
@@ -75,11 +77,11 @@
/* Computing the canonical path of a Win32 file should expose the true
case of filenames, rather than just using the input case */
- File y = new File(ud, f.getPath());
+ File y = new File(userDir, f.getPath());
String ans = y.getPath();
- check(ans, "XyZzY0123\\FOO_bar_BAZ\\GLORPified");
- check(ans, "xyzzy0123\\foo_bar_baz\\glorpified");
- check(ans, "XYZZY0123\\FOO_BAR_BAZ\\GLORPIFIED");
+ check(ans, relative + "\\" + "XyZzY0123\\FOO_bar_BAZ\\GLORPified");
+ check(ans, relative + "\\" + "xyzzy0123\\foo_bar_baz\\glorpified");
+ check(ans, relative + "\\" + "XYZZY0123\\FOO_BAR_BAZ\\GLORPIFIED");
}
private static void checkWild(File f) throws Exception {
@@ -91,18 +93,18 @@
throw new Exception("Wildcard path not rejected: " + f);
}
- private static void checkWildCards(String ud) throws Exception {
- File d = new File(ud).getCanonicalFile();
+ private static void checkWildCards() throws Exception {
+ File d = new File(baseDir).getCanonicalFile();
checkWild(new File(d, "*.*"));
checkWild(new File(d, "*.???"));
checkWild(new File(new File(d, "*.*"), "foo"));
}
private static void checkRelativePaths() throws Exception {
- String ud = System.getProperty("user.dir").replace('/', '\\');
- checkCaseLookup(ud);
- checkWildCards(ud);
- checkNames(3, true, ud + "\\", "");
+ checkCaseLookup();
+ checkWildCards();
+ String relative = baseDir.substring(userDir.length() + 1);
+ checkNames(3, true, baseDir.toString(), relative);
}
@@ -134,7 +136,8 @@
String ans = exists ? df.getAbsolutePath() : d;
if (!ans.endsWith("\\"))
ans = ans + "\\";
- checkNames(depth, false, ans, d);
+ String relative = baseDir.substring(userDir.length() + 1);
+ checkNames(depth, false, ans + relative, d + relative);
}
private static void checkDrivePaths() throws Exception {
@@ -149,7 +152,7 @@
String s = ("\\\\" + NONEXISTENT_UNC_HOST
+ "\\" + NONEXISTENT_UNC_SHARE);
ensureNon(s);
- checkSlashes(2, false, s, s);
+ checkSlashes(DEPTH, false, s, s);
s = "\\\\" + EXISTENT_UNC_HOST + "\\" + EXISTENT_UNC_SHARE;
if (!(new File(s)).exists()) {
@@ -158,7 +161,7 @@
return;
}
- checkSlashes(2, false, s, s);
+ checkSlashes(DEPTH, false, s, s);
}
@@ -168,9 +171,33 @@
return;
}
if (args.length > 0) debug = true;
+ userDir = System.getProperty("user.dir");
+ baseDir = initTestData(6);
checkRelativePaths();
checkDrivePaths();
checkUncPaths();
}
+ private static String initTestData(int maxDepth) throws IOException {
+ File parent = new File(System.getProperty("user.dir"));
+ String baseDir = null;
+ maxDepth = maxDepth < DEPTH + 2 ? DEPTH + 2 : maxDepth;
+ for (int i = 0; i < maxDepth; i ++) {
+ File dir1 = new File(parent, gensym());
+ dir1.mkdir();
+ if (i != 0) {
+ File dir2 = new File(parent, gensym());
+ dir2.mkdir();
+ File f1 = new File(parent, gensym());
+ f1.createNewFile();
+ File f2 = new File(parent, gensym());
+ f2.createNewFile();
+ }
+ if (i == DEPTH + 1) {
+ baseDir = dir1.getAbsolutePath();
+ }
+ parent = dir1;
+ }
+ return baseDir;
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/StringContentEqualsBug.java Mon Jun 03 23:23:20 2013 -0700
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8014477
+ * @summary test String.contentEquals(StringBuffer)
+ */
+public class StringContentEqualsBug {
+
+ static abstract class Task extends Thread {
+ volatile StringBuffer sb;
+ volatile Exception exception;
+
+ Task(StringBuffer sb) {
+ this.sb = sb;
+ }
+
+ @Override
+ public void run() {
+ try {
+ StringBuffer sb;
+ while ((sb = this.sb) != null) {
+ doWith(sb);
+ }
+ }
+ catch (Exception e) {
+ exception = e;
+ }
+ }
+
+ protected abstract void doWith(StringBuffer sb);
+ }
+
+ static class Tester extends Task {
+ Tester(StringBuffer sb) {
+ super(sb);
+ }
+
+ @Override
+ protected void doWith(StringBuffer sb) {
+ "AA".contentEquals(sb);
+ }
+ }
+
+ static class Disturber extends Task {
+ Disturber(StringBuffer sb) {
+ super(sb);
+ }
+
+ @Override
+ protected void doWith(StringBuffer sb) {
+ sb.setLength(0);
+ sb.trimToSize();
+ sb.append("AA");
+ }
+ }
+
+
+ public static void main(String[] args) throws Exception {
+ StringBuffer sb = new StringBuffer();
+ Task[] tasks = new Task[3];
+ (tasks[0] = new Tester(sb)).start();
+ for (int i = 1; i < tasks.length; i++) {
+ (tasks[i] = new Disturber(sb)).start();
+ }
+
+ try
+ {
+ // wait at most 5 seconds for any of the threads to throw exception
+ for (int i = 0; i < 20; i++) {
+ for (Task task : tasks) {
+ if (task.exception != null) {
+ throw task.exception;
+ }
+ }
+ Thread.sleep(250L);
+ }
+ }
+ finally {
+ for (Task task : tasks) {
+ task.sb = null;
+ task.join();
+ }
+ }
+ }
+}
--- a/jdk/test/java/lang/StringBuffer/ToStringCache.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/test/java/lang/StringBuffer/ToStringCache.java Mon Jun 03 23:23:20 2013 -0700
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 8013395
+ * @bug 8013395 8014814
* @summary Test StringBuffer.toString caching
*/
@@ -199,6 +199,28 @@
b = sb.toString();
checkUnequal(a, b);
+ // Extra checks that append(null) works correctly
+
+ sb.append((String)null);
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.append((StringBuffer)null);
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.append((StringBuilder)null);
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.append((CharSequence)null);
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
// non-mutating methods
// Reset to known value
--- a/jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java Mon Jun 03 23:23:20 2013 -0700
@@ -22,13 +22,18 @@
*/
/*
+ * The -XX:MarkSweepAlwaysCompactCount=1 argument below makes sure serial gc
+ * compacts the heap at every full gc so that the usage is correctly updated.
+ */
+
+/*
* @test
* @bug 4892507
* @summary Basic Test for MemoryPool.resetPeakUsage()
* @author Mandy Chung
*
* @build ResetPeakMemoryUsage MemoryUtil
- * @run main/othervm -XX:+UseSerialGC -Xmn8m ResetPeakMemoryUsage
+ * @run main/othervm -XX:+UseSerialGC -XX:MarkSweepAlwaysCompactCount=1 -Xmn8m ResetPeakMemoryUsage
* @run main/othervm -XX:+UseConcMarkSweepGC -Xmn8m ResetPeakMemoryUsage
* @run main/othervm -XX:+UseParallelGC -Xmn8m ResetPeakMemoryUsage
* @run main/othervm -XX:+UseG1GC -Xmn8m -XX:G1HeapRegionSize=1m ResetPeakMemoryUsage
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/ref/OOMEInReferenceHandler.java Mon Jun 03 23:23:20 2013 -0700
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 7038914
+ * @summary Verify that the reference handler does not die after an OOME allocating the InterruptedException object
+ * @run main/othervm -Xmx16M -XX:-UseTLAB OOMEInReferenceHandler
+ * @author peter.levart@gmail.com
+ */
+
+import java.lang.ref.*;
+
+public class OOMEInReferenceHandler {
+ static Object[] fillHeap() {
+ Object[] first = null, last = null;
+ int size = 1 << 20;
+ while (size > 0) {
+ try {
+ Object[] array = new Object[size];
+ if (first == null) {
+ first = array;
+ } else {
+ last[0] = array;
+ }
+ last = array;
+ } catch (OutOfMemoryError oome) {
+ size = size >>> 1;
+ }
+ }
+ return first;
+ }
+
+ public static void main(String[] args) throws Exception {
+ // preinitialize the InterruptedException class so that the reference handler
+ // does not die due to OOME when loading the class if it is the first use
+ InterruptedException ie = new InterruptedException("dummy");
+
+ ThreadGroup tg = Thread.currentThread().getThreadGroup();
+ for (
+ ThreadGroup tgn = tg;
+ tgn != null;
+ tg = tgn, tgn = tg.getParent()
+ )
+ ;
+
+ Thread[] threads = new Thread[tg.activeCount()];
+ Thread referenceHandlerThread = null;
+ int n = tg.enumerate(threads);
+ for (int i = 0; i < n; i++) {
+ if ("Reference Handler".equals(threads[i].getName())) {
+ referenceHandlerThread = threads[i];
+ }
+ }
+
+ if (referenceHandlerThread == null) {
+ throw new IllegalStateException("Couldn't find Reference Handler thread.");
+ }
+
+ ReferenceQueue<Object> refQueue = new ReferenceQueue<>();
+ Object referent = new Object();
+ WeakReference<Object> weakRef = new WeakReference<>(referent, refQueue);
+
+ Object waste = fillHeap();
+
+ referenceHandlerThread.interrupt();
+
+ // allow referenceHandlerThread some time to throw OOME
+ Thread.sleep(500L);
+
+ // release waste & referent
+ waste = null;
+ referent = null;
+
+ // wait at most 10 seconds for success or failure
+ for (int i = 0; i < 20; i++) {
+ if (refQueue.poll() != null) {
+ // Reference Handler thread still working -> success
+ return;
+ }
+ System.gc();
+ Thread.sleep(500L); // wait a little to allow GC to do it's work before allocating objects
+ if (!referenceHandlerThread.isAlive()) {
+ // Reference Handler thread died -> failure
+ throw new Exception("Reference Handler thread died.");
+ }
+ }
+
+ // no sure answer after 10 seconds
+ throw new IllegalStateException("Reference Handler thread stuck.");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/file/Files/FaultyFileSystem.java Mon Jun 03 23:23:20 2013 -0700
@@ -0,0 +1,499 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.IOException;
+import java.net.URI;
+import java.nio.channels.SeekableByteChannel;
+import java.nio.file.AccessMode;
+import java.nio.file.CopyOption;
+import java.nio.file.DirectoryIteratorException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileStore;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystemAlreadyExistsException;
+import java.nio.file.FileSystemNotFoundException;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.OpenOption;
+import java.nio.file.Path;
+import java.nio.file.PathMatcher;
+import java.nio.file.WatchService;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.FileAttribute;
+import java.nio.file.attribute.FileAttributeView;
+import java.nio.file.attribute.UserPrincipalLookupService;
+import java.nio.file.spi.FileSystemProvider;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.function.Supplier;
+
+/**
+ * A {@code FileSystem} that helps testing by trigger exception throwing based on filenames.
+ */
+class FaultyFileSystem extends FileSystem {
+ final Path root;
+ final boolean removeRootAfterClose;
+ final FileSystem delegate;
+ boolean isOpen;
+
+ FaultyFileSystem(Path root) throws IOException {
+ if (root == null) {
+ root = Files.createTempDirectory("faultyFS");
+ removeRootAfterClose = true;
+ } else {
+ if (! Files.isDirectory(root)) {
+ throw new IllegalArgumentException("must be a directory.");
+ }
+ removeRootAfterClose = false;
+ }
+ this.root = root;
+ delegate = root.getFileSystem();
+ isOpen = true;
+ }
+
+ private static Path unwrap(Path p) {
+ return PassThroughFileSystem.unwrap(p);
+ }
+
+ Path getRoot() {
+ return new PassThroughFileSystem.PassThroughPath(this, root);
+ }
+
+ @Override
+ public void close() throws IOException {
+ if (isOpen) {
+ if (removeRootAfterClose) {
+ TestUtil.removeAll(root);
+ }
+ isOpen = false;
+ }
+ }
+
+ @Override
+ public FileSystemProvider provider() {
+ return FaultyFSProvider.getInstance();
+ }
+
+ @Override
+ public boolean isOpen() {
+ return isOpen;
+ }
+
+ @Override
+ public boolean isReadOnly() {
+ return delegate.isReadOnly();
+ }
+
+ @Override
+ public String getSeparator() {
+ return delegate.getSeparator();
+ }
+
+ private <T> Iterable<T> SoleIterable(final T element) {
+ return new Iterable<T>() {
+ @Override
+ public Iterator<T> iterator() {
+ return new Iterator<T>() {
+ private T soleElement = element;
+
+ @Override
+ public boolean hasNext() {
+ return soleElement != null;
+ }
+
+ @Override
+ public T next() {
+ try {
+ return soleElement;
+ } finally {
+ soleElement = null;
+ }
+ }
+ };
+ }
+ };
+ }
+
+ @Override
+ public Iterable<Path> getRootDirectories() {
+ return SoleIterable(getRoot());
+ }
+
+ @Override
+ public Iterable<FileStore> getFileStores() {
+ FileStore store;
+ try {
+ store = Files.getFileStore(root);
+ } catch (IOException ioe) {
+ store = null;
+ }
+ return SoleIterable(store);
+ }
+
+ @Override
+ public Set<String> supportedFileAttributeViews() {
+ // assume that unwrapped objects aren't exposed
+ return delegate.supportedFileAttributeViews();
+ }
+
+ @Override
+ public Path getPath(String first, String... more) {
+ return new PassThroughFileSystem.PassThroughPath(this, delegate.getPath(first, more));
+ }
+
+ @Override
+ public PathMatcher getPathMatcher(String syntaxAndPattern) {
+ final PathMatcher matcher = delegate.getPathMatcher(syntaxAndPattern);
+ return new PathMatcher() {
+ @Override
+ public boolean matches(Path path) {
+ return matcher.matches(unwrap(path));
+ }
+ };
+ }
+
+ @Override
+ public UserPrincipalLookupService getUserPrincipalLookupService() {
+ // assume that unwrapped objects aren't exposed
+ return delegate.getUserPrincipalLookupService();
+ }
+
+ @Override
+ public WatchService newWatchService() throws IOException {
+ // to keep it simple
+ throw new UnsupportedOperationException();
+ }
+
+ static class FaultyException extends IOException {
+ FaultyException() {
+ super("fault triggered.");
+ }
+ }
+
+ static class FaultyFSProvider extends FileSystemProvider {
+ private static final String SCHEME = "faulty";
+ private static volatile FaultyFileSystem delegate;
+ private static FaultyFSProvider INSTANCE = new FaultyFSProvider();
+ private boolean enabled;
+
+ private FaultyFSProvider() {}
+
+ public static FaultyFSProvider getInstance() {
+ return INSTANCE;
+ }
+
+ public void setFaultyMode(boolean enable) {
+ enabled = enable;
+ }
+
+ private void triggerEx(String filename, String... names) throws IOException {
+ if (! enabled) {
+ return;
+ }
+
+ if (filename.equals("SecurityException")) {
+ throw new SecurityException("FaultyFS", new FaultyException());
+ }
+
+ if (filename.equals("IOException")) {
+ throw new FaultyException();
+ }
+
+ for (String name: names) {
+ if (name.equals(filename)) {
+ throw new FaultyException();
+ }
+ }
+ }
+
+ private void triggerEx(Path path, String... names) throws IOException {
+ triggerEx(path.getFileName().toString(), names);
+ }
+
+ @Override
+ public String getScheme() {
+ return SCHEME;
+ }
+
+ private void checkScheme(URI uri) {
+ if (!uri.getScheme().equalsIgnoreCase(SCHEME))
+ throw new IllegalArgumentException();
+ }
+
+ private void checkUri(URI uri) {
+ checkScheme(uri);
+ if (!uri.getSchemeSpecificPart().equals("///"))
+ throw new IllegalArgumentException();
+ }
+
+ @Override
+ public FileSystem newFileSystem(Path fakeRoot, Map<String,?> env)
+ throws IOException
+ {
+ if (env != null && env.keySet().contains("IOException")) {
+ triggerEx("IOException");
+ }
+
+ synchronized (FaultyFSProvider.class) {
+ if (delegate != null && delegate.isOpen())
+ throw new FileSystemAlreadyExistsException();
+ FaultyFileSystem result = new FaultyFileSystem(fakeRoot);
+ delegate = result;
+ return result;
+ }
+ }
+
+ @Override
+ public FileSystem newFileSystem(URI uri, Map<String,?> env)
+ throws IOException
+ {
+ if (env != null && env.keySet().contains("IOException")) {
+ triggerEx("IOException");
+ }
+
+ checkUri(uri);
+ synchronized (FaultyFSProvider.class) {
+ if (delegate != null && delegate.isOpen())
+ throw new FileSystemAlreadyExistsException();
+ FaultyFileSystem result = new FaultyFileSystem(null);
+ delegate = result;
+ return result;
+ }
+ }
+
+ @Override
+ public FileSystem getFileSystem(URI uri) {
+ checkUri(uri);
+ FileSystem result = delegate;
+ if (result == null)
+ throw new FileSystemNotFoundException();
+ return result;
+ }
+
+ @Override
+ public Path getPath(URI uri) {
+ checkScheme(uri);
+ if (delegate == null)
+ throw new FileSystemNotFoundException();
+
+ // only allow absolute path
+ String path = uri.getSchemeSpecificPart();
+ if (! path.startsWith("///")) {
+ throw new IllegalArgumentException();
+ }
+ return new PassThroughFileSystem.PassThroughPath(delegate, delegate.root.resolve(path.substring(3)));
+ }
+
+ @Override
+ public void setAttribute(Path file, String attribute, Object value, LinkOption... options)
+ throws IOException
+ {
+ triggerEx(file, "setAttribute");
+ Files.setAttribute(unwrap(file), attribute, value, options);
+ }
+
+ @Override
+ public Map<String,Object> readAttributes(Path file, String attributes, LinkOption... options)
+ throws IOException
+ {
+ triggerEx(file, "readAttributes");
+ return Files.readAttributes(unwrap(file), attributes, options);
+ }
+
+ @Override
+ public <V extends FileAttributeView> V getFileAttributeView(Path file,
+ Class<V> type,
+ LinkOption... options)
+ {
+ return Files.getFileAttributeView(unwrap(file), type, options);
+ }
+
+ @Override
+ public <A extends BasicFileAttributes> A readAttributes(Path file,
+ Class<A> type,
+ LinkOption... options)
+ throws IOException
+ {
+ triggerEx(file, "readAttributes");
+ return Files.readAttributes(unwrap(file), type, options);
+ }
+
+ @Override
+ public void delete(Path file) throws IOException {
+ triggerEx(file, "delete");
+ Files.delete(unwrap(file));
+ }
+
+ @Override
+ public void createSymbolicLink(Path link, Path target, FileAttribute<?>... attrs)
+ throws IOException
+ {
+ triggerEx(target, "createSymbolicLink");
+ Files.createSymbolicLink(unwrap(link), unwrap(target), attrs);
+ }
+
+ @Override
+ public void createLink(Path link, Path existing) throws IOException {
+ triggerEx(existing, "createLink");
+ Files.createLink(unwrap(link), unwrap(existing));
+ }
+
+ @Override
+ public Path readSymbolicLink(Path link) throws IOException {
+ Path target = Files.readSymbolicLink(unwrap(link));
+ triggerEx(target, "readSymbolicLink");
+ return new PassThroughFileSystem.PassThroughPath(delegate, target);
+ }
+
+
+ @Override
+ public void copy(Path source, Path target, CopyOption... options) throws IOException {
+ triggerEx(source, "copy");
+ Files.copy(unwrap(source), unwrap(target), options);
+ }
+
+ @Override
+ public void move(Path source, Path target, CopyOption... options) throws IOException {
+ triggerEx(source, "move");
+ Files.move(unwrap(source), unwrap(target), options);
+ }
+
+ private DirectoryStream<Path> wrap(final DirectoryStream<Path> stream) {
+ return new DirectoryStream<Path>() {
+ @Override
+ public Iterator<Path> iterator() {
+ final Iterator<Path> itr = stream.iterator();
+ return new Iterator<Path>() {
+ private Path next = null;
+ @Override
+ public boolean hasNext() {
+ if (next == null) {
+ if (itr.hasNext()) {
+ next = itr.next();
+ } else {
+ return false;
+ }
+ }
+ if (next != null) {
+ try {
+ triggerEx(next, "DirectoryIteratorException");
+ } catch (IOException ioe) {
+ throw new DirectoryIteratorException(ioe);
+ } catch (SecurityException se) {
+ // ??? Does DS throw SecurityException during iteration?
+ next = null;
+ return hasNext();
+ }
+ }
+ return (next != null);
+ }
+ @Override
+ public Path next() {
+ try {
+ if (next != null || hasNext()) {
+ return new PassThroughFileSystem.PassThroughPath(delegate, next);
+ } else {
+ throw new NoSuchElementException();
+ }
+ } finally {
+ next = null;
+ }
+ }
+
+ @Override
+ public void remove() {
+ itr.remove();
+ }
+ };
+ }
+ @Override
+ public void close() throws IOException {
+ stream.close();
+ }
+ };
+ }
+
+ @Override
+ public DirectoryStream<Path> newDirectoryStream(Path dir, DirectoryStream.Filter<? super Path> filter)
+ throws IOException
+ {
+ triggerEx(dir, "newDirectoryStream");
+ return wrap(Files.newDirectoryStream(unwrap(dir), filter));
+ }
+
+ @Override
+ public void createDirectory(Path dir, FileAttribute<?>... attrs)
+ throws IOException
+ {
+ triggerEx(dir, "createDirectory");
+ Files.createDirectory(unwrap(dir), attrs);
+ }
+
+ @Override
+ public SeekableByteChannel newByteChannel(Path file,
+ Set<? extends OpenOption> options,
+ FileAttribute<?>... attrs)
+ throws IOException
+ {
+ triggerEx(file, "newByteChannel");
+ return Files.newByteChannel(unwrap(file), options, attrs);
+ }
+
+
+ @Override
+ public boolean isHidden(Path file) throws IOException {
+ triggerEx(file, "isHidden");
+ return Files.isHidden(unwrap(file));
+ }
+
+ @Override
+ public FileStore getFileStore(Path file) throws IOException {
+ triggerEx(file, "getFileStore");
+ return Files.getFileStore(unwrap(file));
+ }
+
+ @Override
+ public boolean isSameFile(Path file, Path other) throws IOException {
+ triggerEx(file, "isSameFile");
+ return Files.isSameFile(unwrap(file), unwrap(other));
+ }
+
+ @Override
+ public void checkAccess(Path file, AccessMode... modes)
+ throws IOException
+ {
+ triggerEx(file, "checkAccess");
+ // hack
+ if (modes.length == 0) {
+ if (Files.exists(unwrap(file)))
+ return;
+ else
+ throw new NoSuchFileException(file.toString());
+ }
+ throw new RuntimeException("not implemented yet");
+ }
+ }
+}
--- a/jdk/test/java/nio/file/Files/PassThroughFileSystem.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/test/java/nio/file/Files/PassThroughFileSystem.java Mon Jun 03 23:23:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. 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
@@ -304,7 +304,7 @@
public DirectoryStream<Path> newDirectoryStream(Path dir, DirectoryStream.Filter<? super Path> filter)
throws IOException
{
- return wrap(Files.newDirectoryStream(dir, filter));
+ return wrap(Files.newDirectoryStream(unwrap(dir), filter));
}
@Override
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/file/Files/StreamTest.java Mon Jun 03 23:23:20 2013 -0700
@@ -0,0 +1,621 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8006884
+ * @summary Unit test for java.nio.file.Files
+ * @library ..
+ * @build PassThroughFileSystem FaultyFileSystem
+ * @run testng StreamTest
+ */
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.charset.Charset;
+import java.nio.charset.MalformedInputException;
+import java.nio.file.DirectoryIteratorException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileSystemLoopException;
+import java.nio.file.FileVisitOption;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.Arrays;
+import java.util.Comparators;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.function.BiPredicate;
+import java.util.stream.CloseableStream;
+import java.util.stream.Collectors;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test(groups = "unit")
+public class StreamTest {
+ /**
+ * Default test folder
+ * testFolder - empty
+ * - file
+ * - dir - d1
+ * - f1
+ * - lnDir2 (../dir2)
+ * - dir2
+ * - linkDir (./dir)
+ * - linkFile(./file)
+ */
+ static Path testFolder;
+ static boolean supportsLinks;
+ static Path[] level1;
+ static Path[] all;
+ static Path[] all_folowLinks;
+
+ @BeforeClass
+ void setupTestFolder() throws IOException {
+ testFolder = TestUtil.createTemporaryDirectory();
+ supportsLinks = TestUtil.supportsLinks(testFolder);
+ TreeSet<Path> set = new TreeSet<>();
+
+ // Level 1
+ Path empty = testFolder.resolve("empty");
+ Path file = testFolder.resolve("file");
+ Path dir = testFolder.resolve("dir");
+ Path dir2 = testFolder.resolve("dir2");
+ Files.createDirectory(empty);
+ Files.createFile(file);
+ Files.createDirectory(dir);
+ Files.createDirectory(dir2);
+ set.add(empty);
+ set.add(file);
+ set.add(dir);
+ set.add(dir2);
+ if (supportsLinks) {
+ Path tmp = testFolder.resolve("linkDir");
+ Files.createSymbolicLink(tmp, dir);
+ set.add(tmp);
+ tmp = testFolder.resolve("linkFile");
+ Files.createSymbolicLink(tmp, file);
+ set.add(tmp);
+ }
+ level1 = set.toArray(new Path[0]);
+
+ // Level 2
+ Path tmp = dir.resolve("d1");
+ Files.createDirectory(tmp);
+ set.add(tmp);
+ tmp = dir.resolve("f1");
+ Files.createFile(tmp);
+ set.add(tmp);
+ if (supportsLinks) {
+ tmp = dir.resolve("lnDir2");
+ Files.createSymbolicLink(tmp, dir2);
+ set.add(tmp);
+ }
+ // walk include starting folder
+ set.add(testFolder);
+ all = set.toArray(new Path[0]);
+
+ // Follow links
+ if (supportsLinks) {
+ tmp = testFolder.resolve("linkDir");
+ set.add(tmp.resolve("d1"));
+ set.add(tmp.resolve("f1"));
+ tmp = tmp.resolve("lnDir2");
+ set.add(tmp);
+ }
+ all_folowLinks = set.toArray(new Path[0]);
+ }
+
+ @AfterClass
+ void cleanupTestFolder() throws IOException {
+ TestUtil.removeAll(testFolder);
+ }
+
+ public void testBasic() {
+ try (CloseableStream<Path> s = Files.list(testFolder)) {
+ Object[] actual = s.sorted(Comparators.naturalOrder()).toArray();
+ assertEquals(actual, level1);
+ } catch (IOException ioe) {
+ fail("Unexpected IOException");
+ }
+
+ try (CloseableStream<Path> s = Files.list(testFolder.resolve("empty"))) {
+ int count = s.mapToInt(p -> 1).reduce(0, Integer::sum);
+ assertEquals(count, 0, "Expect empty stream.");
+ } catch (IOException ioe) {
+ fail("Unexpected IOException");
+ }
+ }
+
+ public void testWalk() {
+ try (CloseableStream<Path> s = Files.walk(testFolder)) {
+ Object[] actual = s.sorted(Comparators.naturalOrder()).toArray();
+ assertEquals(actual, all);
+ } catch (IOException ioe) {
+ fail("Unexpected IOException");
+ }
+ }
+
+ public void testWalkOneLevel() {
+ try (CloseableStream<Path> s = Files.walk(testFolder, 1)) {
+ Object[] actual = s.filter(path -> ! path.equals(testFolder))
+ .sorted(Comparators.naturalOrder())
+ .toArray();
+ assertEquals(actual, level1);
+ } catch (IOException ioe) {
+ fail("Unexpected IOException");
+ }
+ }
+
+ public void testWalkFollowLink() {
+ // If link is not supported, the directory structure won't have link.
+ // We still want to test the behavior with FOLLOW_LINKS option.
+ try (CloseableStream<Path> s = Files.walk(testFolder, FileVisitOption.FOLLOW_LINKS)) {
+ Object[] actual = s.sorted(Comparators.naturalOrder()).toArray();
+ assertEquals(actual, all_folowLinks);
+ } catch (IOException ioe) {
+ fail("Unexpected IOException");
+ }
+ }
+
+ private void validateFileSystemLoopException(Path start, Path... causes) {
+ try (CloseableStream<Path> s = Files.walk(start, FileVisitOption.FOLLOW_LINKS)) {
+ try {
+ int count = s.mapToInt(p -> 1).reduce(0, Integer::sum);
+ fail("Should got FileSystemLoopException, but got " + count + "elements.");
+ } catch (UncheckedIOException uioe) {
+ IOException ioe = uioe.getCause();
+ if (ioe instanceof FileSystemLoopException) {
+ FileSystemLoopException fsle = (FileSystemLoopException) ioe;
+ boolean match = false;
+ for (Path cause: causes) {
+ if (fsle.getFile().equals(cause.toString())) {
+ match = true;
+ break;
+ }
+ }
+ assertTrue(match);
+ } else {
+ fail("Unexpected UncheckedIOException cause " + ioe.toString());
+ }
+ }
+ } catch(IOException ex) {
+ fail("Unexpected IOException " + ex);
+ }
+ }
+
+ public void testWalkFollowLinkLoop() {
+ if (!supportsLinks) {
+ return;
+ }
+
+ // Loops.
+ try {
+ Path dir = testFolder.resolve("dir");
+ Path linkdir = testFolder.resolve("linkDir");
+ Path d1 = dir.resolve("d1");
+ Path cause = d1.resolve("lnSelf");
+ Files.createSymbolicLink(cause, d1);
+
+ // loop in descendant.
+ validateFileSystemLoopException(dir, cause);
+ // loop in self
+ validateFileSystemLoopException(d1, cause);
+ // start from other place via link
+ validateFileSystemLoopException(linkdir,
+ linkdir.resolve(Paths.get("d1", "lnSelf")));
+ Files.delete(cause);
+
+ // loop to parent.
+ cause = d1.resolve("lnParent");
+ Files.createSymbolicLink(cause, dir);
+
+ // loop should be detected at test/dir/d1/lnParent/d1
+ validateFileSystemLoopException(d1, cause.resolve("d1"));
+ // loop should be detected at link
+ validateFileSystemLoopException(dir, cause);
+ // loop should be detected at test/linkdir/d1/lnParent
+ // which is test/dir we have visited via test/linkdir
+ validateFileSystemLoopException(linkdir,
+ linkdir.resolve(Paths.get("d1", "lnParent")));
+ Files.delete(cause);
+
+ // cross loop
+ Path dir2 = testFolder.resolve("dir2");
+ cause = dir2.resolve("lnDir");
+ Files.createSymbolicLink(cause, dir);
+ validateFileSystemLoopException(dir,
+ dir.resolve(Paths.get("lnDir2", "lnDir")));
+ validateFileSystemLoopException(dir2,
+ dir2.resolve(Paths.get("lnDir", "lnDir2")));
+ validateFileSystemLoopException(linkdir,
+ linkdir.resolve(Paths.get("lnDir2", "lnDir")));
+ } catch(IOException ioe) {
+ fail("Unexpected IOException " + ioe);
+ }
+ }
+
+ private static class PathBiPredicate implements BiPredicate<Path, BasicFileAttributes> {
+ private final BiPredicate<Path, BasicFileAttributes> pred;
+ private final Set<Path> visited = new TreeSet<Path>();
+
+ PathBiPredicate(BiPredicate<Path, BasicFileAttributes> pred) {
+ this.pred = Objects.requireNonNull(pred);
+ }
+
+ public boolean test(Path path, BasicFileAttributes attrs) {
+ visited.add(path);
+ return pred.test(path, attrs);
+ }
+
+ public Path[] visited() {
+ return visited.toArray(new Path[0]);
+ }
+ }
+
+ public void testFind() throws IOException {
+ PathBiPredicate pred = new PathBiPredicate((path, attrs) -> true);
+
+ try (CloseableStream<Path> s = Files.find(testFolder, Integer.MAX_VALUE, pred)) {
+ Set<Path> result = s.collect(Collectors.toCollection(TreeSet::new));
+ assertEquals(pred.visited(), all);
+ assertEquals(result.toArray(new Path[0]), pred.visited());
+ }
+
+ pred = new PathBiPredicate((path, attrs) -> attrs.isSymbolicLink());
+ try (CloseableStream<Path> s = Files.find(testFolder, Integer.MAX_VALUE, pred)) {
+ s.forEach(path -> assertTrue(Files.isSymbolicLink(path)));
+ assertEquals(pred.visited(), all);
+ }
+
+ pred = new PathBiPredicate((path, attrs) ->
+ path.getFileName().toString().startsWith("e"));
+ try (CloseableStream<Path> s = Files.find(testFolder, Integer.MAX_VALUE, pred)) {
+ s.forEach(path -> assertEquals(path.getFileName().toString(), "empty"));
+ assertEquals(pred.visited(), all);
+ }
+
+ pred = new PathBiPredicate((path, attrs) ->
+ path.getFileName().toString().startsWith("l") && attrs.isRegularFile());
+ try (CloseableStream<Path> s = Files.find(testFolder, Integer.MAX_VALUE, pred)) {
+ s.forEach(path -> fail("Expect empty stream"));
+ assertEquals(pred.visited(), all);
+ }
+ }
+
+ // Test borrowed from BytesAndLines
+ public void testLines() throws IOException {
+ final Charset US_ASCII = Charset.forName("US-ASCII");
+ Path tmpfile = Files.createTempFile("blah", "txt");
+
+ try {
+ // zero lines
+ assertTrue(Files.size(tmpfile) == 0, "File should be empty");
+ try (CloseableStream<String> s = Files.lines(tmpfile, US_ASCII)) {
+ assertEquals(s.mapToInt(l -> 1).reduce(0, Integer::sum), 0, "No line expected");
+ }
+
+ // one line
+ byte[] hi = { (byte)'h', (byte)'i' };
+ Files.write(tmpfile, hi);
+ try (CloseableStream<String> s = Files.lines(tmpfile, US_ASCII)) {
+ List<String> lines = s.collect(Collectors.toList());
+ assertTrue(lines.size() == 1, "One line expected");
+ assertTrue(lines.get(0).equals("hi"), "'Hi' expected");
+ }
+
+ // two lines using platform's line separator
+ List<String> expected = Arrays.asList("hi", "there");
+ Files.write(tmpfile, expected, US_ASCII);
+ assertTrue(Files.size(tmpfile) > 0, "File is empty");
+ try (CloseableStream<String> s = Files.lines(tmpfile, US_ASCII)) {
+ List<String> lines = s.collect(Collectors.toList());
+ assertTrue(lines.equals(expected), "Unexpected lines");
+ }
+
+ // MalformedInputException
+ byte[] bad = { (byte)0xff, (byte)0xff };
+ Files.write(tmpfile, bad);
+ try (CloseableStream<String> s = Files.lines(tmpfile, US_ASCII)) {
+ try {
+ List<String> lines = s.collect(Collectors.toList());
+ throw new RuntimeException("UncheckedIOException expected");
+ } catch (UncheckedIOException ex) {
+ assertTrue(ex.getCause() instanceof MalformedInputException,
+ "MalformedInputException expected");
+ }
+ }
+
+ // NullPointerException
+ try {
+ Files.lines(null, US_ASCII);
+ throw new RuntimeException("NullPointerException expected");
+ } catch (NullPointerException ignore) { }
+ try {
+ Files.lines(tmpfile, null);
+ throw new RuntimeException("NullPointerException expected");
+ } catch (NullPointerException ignore) { }
+
+ } finally {
+ Files.delete(tmpfile);
+ }
+ }
+
+ public void testDirectoryIteratorException() throws IOException {
+ Path dir = testFolder.resolve("dir2");
+ Path trigger = dir.resolve("DirectoryIteratorException");
+ Files.createFile(trigger);
+ FaultyFileSystem.FaultyFSProvider fsp = FaultyFileSystem.FaultyFSProvider.getInstance();
+ FaultyFileSystem fs = (FaultyFileSystem) fsp.newFileSystem(dir, null);
+
+ try {
+ fsp.setFaultyMode(false);
+ Path fakeRoot = fs.getRoot();
+ try {
+ try (CloseableStream<Path> s = Files.list(fakeRoot)) {
+ s.forEach(path -> assertEquals(path.getFileName().toString(), "DirectoryIteratorException"));
+ }
+ } catch (UncheckedIOException uioe) {
+ fail("Unexpected exception.");
+ }
+
+ fsp.setFaultyMode(true);
+ try {
+ try (DirectoryStream<Path> ds = Files.newDirectoryStream(fakeRoot)) {
+ Iterator<Path> itor = ds.iterator();
+ while (itor.hasNext()) {
+ itor.next();
+ }
+ }
+ fail("Shoule throw DirectoryIteratorException");
+ } catch (DirectoryIteratorException die) {
+ }
+
+ try {
+ try (CloseableStream<Path> s = Files.list(fakeRoot)) {
+ s.forEach(path -> fail("should not get here"));
+ }
+ } catch (UncheckedIOException uioe) {
+ assertTrue(uioe.getCause() instanceof FaultyFileSystem.FaultyException);
+ } catch (DirectoryIteratorException die) {
+ fail("Should have been converted into UncheckedIOException.");
+ }
+ } finally {
+ // Cleanup
+ if (fs != null) {
+ fs.close();
+ }
+ Files.delete(trigger);
+ }
+ }
+
+ public void testUncheckedIOException() throws IOException {
+ Path triggerFile = testFolder.resolve(Paths.get("dir2", "IOException"));
+ Files.createFile(triggerFile);
+ Path triggerDir = testFolder.resolve(Paths.get("empty", "IOException"));
+ Files.createDirectories(triggerDir);
+ Files.createFile(triggerDir.resolve("file"));
+ FaultyFileSystem.FaultyFSProvider fsp = FaultyFileSystem.FaultyFSProvider.getInstance();
+ FaultyFileSystem fs = (FaultyFileSystem) fsp.newFileSystem(testFolder, null);
+
+ try {
+ fsp.setFaultyMode(false);
+ Path fakeRoot = fs.getRoot();
+ try (CloseableStream<Path> s = Files.list(fakeRoot.resolve("dir2"))) {
+ // only one file
+ s.forEach(path -> assertEquals(path.getFileName().toString(), "IOException"));
+ }
+
+ try (CloseableStream<Path> s = Files.walk(fakeRoot.resolve("empty"))) {
+ String[] result = s.map(path -> path.getFileName().toString())
+ .toArray(String[]::new);
+ // ordered as depth-first
+ assertEquals(result, new String[] { "empty", "IOException", "file"});
+ }
+
+ fsp.setFaultyMode(true);
+ try (CloseableStream<Path> s = Files.list(fakeRoot.resolve("dir2"))) {
+ s.forEach(path -> fail("should have caused exception"));
+ } catch (UncheckedIOException uioe) {
+ assertTrue(uioe.getCause() instanceof FaultyFileSystem.FaultyException);
+ }
+
+ try (CloseableStream<Path> s = Files.walk(fakeRoot.resolve("empty"))) {
+ String[] result = s.map(path -> path.getFileName().toString())
+ .toArray(String[]::new);
+ fail("should not reach here due to IOException");
+ } catch (UncheckedIOException uioe) {
+ assertTrue(uioe.getCause() instanceof FaultyFileSystem.FaultyException);
+ }
+
+ try (CloseableStream<Path> s = Files.walk(
+ fakeRoot.resolve("empty").resolve("IOException")))
+ {
+ String[] result = s.map(path -> path.getFileName().toString())
+ .toArray(String[]::new);
+ fail("should not reach here due to IOException");
+ } catch (IOException ioe) {
+ assertTrue(ioe instanceof FaultyFileSystem.FaultyException);
+ } catch (UncheckedIOException ex) {
+ fail("Top level should be repored as is");
+ }
+ } finally {
+ // Cleanup
+ if (fs != null) {
+ fs.close();
+ }
+ Files.delete(triggerFile);
+ TestUtil.removeAll(triggerDir);
+ }
+ }
+
+ public void testSecurityException() throws IOException {
+ Path triggerFile = testFolder.resolve(Paths.get("dir", "SecurityException"));
+ Files.createFile(triggerFile);
+ Path sampleFile = testFolder.resolve(Paths.get("dir", "sample"));
+ Files.createFile(sampleFile);
+ Path triggerDir = testFolder.resolve(Paths.get("dir2", "SecurityException"));
+ Files.createDirectories(triggerDir);
+ Files.createFile(triggerDir.resolve("fileInSE"));
+ Path sample = testFolder.resolve(Paths.get("dir2", "file"));
+ Files.createFile(sample);
+ FaultyFileSystem.FaultyFSProvider fsp = FaultyFileSystem.FaultyFSProvider.getInstance();
+ FaultyFileSystem fs = (FaultyFileSystem) fsp.newFileSystem(testFolder, null);
+
+ try {
+ fsp.setFaultyMode(false);
+ Path fakeRoot = fs.getRoot();
+ // validate setting
+ try (CloseableStream<Path> s = Files.list(fakeRoot.resolve("dir"))) {
+ String[] result = s.map(path -> path.getFileName().toString())
+ .toArray(String[]::new);
+ assertEqualsNoOrder(result, new String[] { "d1","f1", "lnDir2", "SecurityException", "sample" });
+ }
+
+ try (CloseableStream<Path> s = Files.walk(fakeRoot.resolve("dir2"))) {
+ String[] result = s.map(path -> path.getFileName().toString())
+ .toArray(String[]::new);
+ assertEqualsNoOrder(result, new String[] { "dir2", "SecurityException", "fileInSE", "file" });
+ }
+
+ // execute test
+ fsp.setFaultyMode(true);
+ // ignore file cause SecurityException
+ try (CloseableStream<Path> s = Files.walk(fakeRoot.resolve("dir"))) {
+ String[] result = s.map(path -> path.getFileName().toString())
+ .toArray(String[]::new);
+ assertEqualsNoOrder(result, new String[] { "dir", "d1","f1", "lnDir2", "sample" });
+ }
+ // skip folder cause SecurityException
+ try (CloseableStream<Path> s = Files.walk(fakeRoot.resolve("dir2"))) {
+ String[] result = s.map(path -> path.getFileName().toString())
+ .toArray(String[]::new);
+ assertEqualsNoOrder(result, new String[] { "dir2", "file" });
+ }
+
+ // list instead of walk
+ try (CloseableStream<Path> s = Files.list(fakeRoot.resolve("dir"))) {
+ String[] result = s.map(path -> path.getFileName().toString())
+ .toArray(String[]::new);
+ assertEqualsNoOrder(result, new String[] { "d1","f1", "lnDir2", "sample" });
+ }
+ try (CloseableStream<Path> s = Files.list(fakeRoot.resolve("dir2"))) {
+ String[] result = s.map(path -> path.getFileName().toString())
+ .toArray(String[]::new);
+ assertEqualsNoOrder(result, new String[] { "file" });
+ }
+
+ // root cause SecurityException should be reported
+ try (CloseableStream<Path> s = Files.walk(
+ fakeRoot.resolve("dir2").resolve("SecurityException")))
+ {
+ String[] result = s.map(path -> path.getFileName().toString())
+ .toArray(String[]::new);
+ fail("should not reach here due to SecurityException");
+ } catch (SecurityException se) {
+ assertTrue(se.getCause() instanceof FaultyFileSystem.FaultyException);
+ }
+
+ // Walk a file cause SecurityException, we should get SE
+ try (CloseableStream<Path> s = Files.walk(
+ fakeRoot.resolve("dir").resolve("SecurityException")))
+ {
+ String[] result = s.map(path -> path.getFileName().toString())
+ .toArray(String[]::new);
+ fail("should not reach here due to SecurityException");
+ } catch (SecurityException se) {
+ assertTrue(se.getCause() instanceof FaultyFileSystem.FaultyException);
+ }
+
+ // List a file cause SecurityException, we should get SE as cannot read attribute
+ try (CloseableStream<Path> s = Files.list(
+ fakeRoot.resolve("dir2").resolve("SecurityException")))
+ {
+ String[] result = s.map(path -> path.getFileName().toString())
+ .toArray(String[]::new);
+ fail("should not reach here due to SecurityException");
+ } catch (SecurityException se) {
+ assertTrue(se.getCause() instanceof FaultyFileSystem.FaultyException);
+ }
+
+ try (CloseableStream<Path> s = Files.list(
+ fakeRoot.resolve("dir").resolve("SecurityException")))
+ {
+ String[] result = s.map(path -> path.getFileName().toString())
+ .toArray(String[]::new);
+ fail("should not reach here due to SecurityException");
+ } catch (SecurityException se) {
+ assertTrue(se.getCause() instanceof FaultyFileSystem.FaultyException);
+ }
+ } finally {
+ // Cleanup
+ if (fs != null) {
+ fs.close();
+ }
+ Files.delete(triggerFile);
+ Files.delete(sampleFile);
+ Files.delete(sample);
+ TestUtil.removeAll(triggerDir);
+ }
+ }
+
+ public void testConstructException() {
+ try (CloseableStream<String> s = Files.lines(testFolder.resolve("notExist"), Charset.forName("UTF-8"))) {
+ s.forEach(l -> fail("File is not even exist!"));
+ } catch (IOException ioe) {
+ ioe.printStackTrace(System.err);
+ assertTrue(ioe instanceof NoSuchFileException);
+ }
+ }
+
+ public void testClosedStream() throws IOException {
+ try (CloseableStream<Path> s = Files.list(testFolder)) {
+ s.close();
+ Object[] actual = s.sorted(Comparators.naturalOrder()).toArray();
+ assertTrue(actual.length <= level1.length);
+ }
+
+ try (CloseableStream<Path> s = Files.walk(testFolder)) {
+ s.close();
+ Object[] actual = s.sorted(Comparators.naturalOrder()).toArray();
+ fail("Operate on closed stream should throw IllegalStateException");
+ } catch (IllegalStateException ex) {
+ // expected
+ }
+
+ try (CloseableStream<Path> s = Files.find(testFolder, Integer.MAX_VALUE,
+ (p, attr) -> true)) {
+ s.close();
+ Object[] actual = s.sorted(Comparators.naturalOrder()).toArray();
+ fail("Operate on closed stream should throw IllegalStateException");
+ } catch (IllegalStateException ex) {
+ // expected
+ }
+ }
+}
--- a/jdk/test/java/util/Arrays/ParallelSorting.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/test/java/util/Arrays/ParallelSorting.java Mon Jun 03 23:23:20 2013 -0700
@@ -50,11 +50,11 @@
// Array lengths used in a long run (default)
private static final int[] LONG_RUN_LENGTHS = {
- 1, 2, 3, 5, 8, 13, 21, 34, 55, 100, 1000, 10000, 100000, 1000000 };
+ 1000, 10000, 100000, 1000000 };
// Array lengths used in a short run
private static final int[] SHORT_RUN_LENGTHS = {
- 1, 2, 3, 21, 55, 1000, 10000 };
+ 5000, 9000, 10000, 12000 };
// Random initial values used in a long run (default)
private static final long[] LONG_RUN_RANDOMS = { 666, 0xC0FFEE, 999 };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/text/View/8014863/bug8014863.java Mon Jun 03 23:23:20 2013 -0700
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2007, 2013, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8014863
+ * @summary Tests the calculation of the line breaks when a text is inserted
+ * @author Dmitry Markov
+ * @library ../../../regtesthelpers
+ * @build Util
+ * @run main bug8014863
+ */
+
+import sun.awt.SunToolkit;
+
+import javax.swing.*;
+import javax.swing.text.html.HTMLEditorKit;
+import java.awt.*;
+import java.awt.event.KeyEvent;
+
+public class bug8014863 {
+
+ private static JEditorPane editorPane;
+ private static Robot robot;
+ private static SunToolkit toolkit;
+
+ public static void main(String[] args) throws Exception {
+ toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
+ robot = new Robot();
+
+ createAndShowGUI();
+
+ toolkit.realSync();
+
+ Util.hitKeys(robot, KeyEvent.VK_HOME);
+ Util.hitKeys(robot, KeyEvent.VK_O);
+
+ toolkit.realSync();
+
+ if (3 != getNumberOfTextLines()) {
+ throw new RuntimeException("The number of texts lines does not meet the expectation");
+ }
+
+ Util.hitKeys(robot, KeyEvent.VK_N);
+
+ toolkit.realSync();
+
+ if (3 != getNumberOfTextLines()) {
+ throw new RuntimeException("The number of texts lines does not meet the expectation");
+ }
+
+ Util.hitKeys(robot, KeyEvent.VK_E);
+ Util.hitKeys(robot, KeyEvent.VK_SPACE);
+ Util.hitKeys(robot, KeyEvent.VK_T);
+ Util.hitKeys(robot, KeyEvent.VK_W);
+
+ toolkit.realSync();
+
+ if (3 != getNumberOfTextLines()) {
+ throw new RuntimeException("The number of texts lines does not meet the expectation");
+ }
+ }
+
+ private static int getNumberOfTextLines() throws Exception {
+ int numberOfLines = 0;
+ int caretPosition = getCaretPosition();
+ int current = 1;
+ int previous;
+
+ setCaretPosition(current);
+ do {
+ previous = current;
+ Util.hitKeys(robot, KeyEvent.VK_DOWN);
+ toolkit.realSync();
+ current = getCaretPosition();
+ numberOfLines++;
+ } while (current != previous);
+
+ setCaretPosition(caretPosition);
+ return numberOfLines;
+ }
+
+ private static int getCaretPosition() throws Exception {
+ final int[] result = new int[1];
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ result[0] = editorPane.getCaretPosition();
+ }
+ });
+ return result[0];
+ }
+
+ private static void setCaretPosition(final int position) throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ editorPane.setCaretPosition(position);
+ }
+ });
+ }
+
+ private static void createAndShowGUI() throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ try {
+ UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ JFrame frame = new JFrame();
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+ editorPane = new JEditorPane();
+ HTMLEditorKit editorKit = new HTMLEditorKit();
+ editorPane.setEditorKit(editorKit);
+ editorPane.setText("<p>qqqq <em>pp</em> qqqq <em>pp</em> " +
+ "qqqq <em>pp</em> qqqq <em>pp</em> qqqq <em>pp</em> qqqq <em>pp" +
+ "</em> qqqq <em>pp</em> qqqq <em>pp</em> qqqq <em>pp</em> qqqq</p>");
+ editorPane.setCaretPosition(1);
+
+ frame.add(editorPane);
+ frame.setSize(200, 200);
+ frame.setVisible(true);
+ }
+ });
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/text/html/parser/Parser/7011777/bug7011777.java Mon Jun 03 23:23:20 2013 -0700
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 7011777
+ * @summary Tests correct parsing of a HTML comment inside 'script' tags
+ * @author Dmitry Markov
+ */
+
+import javax.swing.text.html.HTMLEditorKit;
+import javax.swing.text.html.parser.ParserDelegator;
+import java.io.StringReader;
+
+public class bug7011777 {
+ static String comment = "<!--\n" +
+ "function foo() {\n" +
+ " var tag1 = \"</script>\";\n" +
+ " var tag2 = \"<div>\";\n" +
+ " var tag3 = \"</div>\";\n" +
+ " var tag4 = \"<script>\";\n" +
+ "}\n" +
+ "// -->";
+ static String html = "<script>" + comment + "</script>";
+ public static void main(String[] args) throws Exception {
+ new ParserDelegator().parse(new StringReader(html), new MyParserCallback(), true);
+ }
+
+ static class MyParserCallback extends HTMLEditorKit.ParserCallback {
+
+ @Override
+ public void handleComment(char[] data, int pos) {
+ String commentWithoutTags = comment.substring("<!--".length(), comment.length() - "-->".length());
+ String str = new String(data);
+ if (!commentWithoutTags.equals(str)) {
+ System.out.println("Sample string:\n" + commentWithoutTags);
+ System.out.println("Returned string:\n" + str);
+ throw new RuntimeException("Test Failed, sample and returned strings are mismatched!");
+ }
+ }
+ }
+
+}
--- a/jdk/test/sun/awt/datatransfer/SuplementaryCharactersTransferTest.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/test/sun/awt/datatransfer/SuplementaryCharactersTransferTest.java Mon Jun 03 23:23:20 2013 -0700
@@ -146,12 +146,6 @@
}
@Override
- protected Image platformImageBytesOrStreamToImage(InputStream str,
- byte[] bytes, long format) throws IOException {
- throw new UnsupportedOperationException("Not supported yet.");
- }
-
- @Override
protected byte[] imageToPlatformBytes(Image image, long format)
throws IOException {
throw new UnsupportedOperationException("Not supported yet.");
@@ -161,5 +155,10 @@
public ToolkitThreadBlockedHandler getToolkitThreadBlockedHandler() {
throw new UnsupportedOperationException("Not supported yet.");
}
+
+ @Override
+ protected Image platformImageBytesToImage(byte[] bytes, long format) throws IOException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
}
}
\ No newline at end of file
--- a/jdk/test/sun/management/jdp/JdpTest.sh Thu May 30 10:58:21 2013 -0700
+++ b/jdk/test/sun/management/jdp/JdpTest.sh Mon Jun 03 23:23:20 2013 -0700
@@ -2,17 +2,17 @@
# Copyright (c) 2011, 2012, Oracle and/or its affiliates. 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.
@@ -22,8 +22,8 @@
# questions.
# @test
-# @bug 7169888
-# @compile -XDignore.symbol.file JdpUnitTest.java JdpClient.java JdpDoSomething.java
+# @bug 7169888
+# @compile -XDignore.symbol.file JdpUnitTest.java JdpClient.java JdpDoSomething.java
# @run shell JdpTest.sh --jtreg --no-compile
# @summary No word Failed expected in the test output
@@ -44,17 +44,20 @@
_logname=".classes/output.txt"
_last_pid=""
+_ip="224.0.23.178"
+_port="7095"
+_jmxport="4545"
_do_compile(){
# If the test run without JTReg, we have to compile it by our self
# Under JTReg see @compile statement above
- # sun.* packages is not included to symbol file lib/ct.sym so we have
+ # sun.* packages is not included to symbol file lib/ct.sym so we have
# to ignore it
if [ ! -d ${_testclasses} ]
then
mkdir -p ${_testclasses}
- fi
+ fi
rm -f ${_testclasses}/*.class
@@ -64,11 +67,11 @@
JdpDoSomething.java \
JdpClient.java
-
+
if [ ! -f ${_testclasses}/JdpDoSomething.class -o ! -f ${_testclasses}/JdpClient.class -o ! -f ${_testclasses}/JdpUnitTest.class ]
then
echo "ERROR: Can't compile"
- exit -1
+ exit 255
fi
}
@@ -84,10 +87,10 @@
npid=`_get_pid`
if [ "${npid}" = "" ]
then
- echo "ERROR: Test app not started"
+ echo "ERROR: Test app not started. Please check machine resources before filing a bug."
if [ "${_jtreg}" = "yes" ]
then
- exit -1
+ exit 255
fi
fi
}
@@ -100,53 +103,53 @@
rm ${_lockFileName}
# wait until VM is actually shuts down
- while true
+ while true
do
npid=`_get_pid`
- if [ "${npid}" = "" ]
+ if [ "${npid}" = "" ]
then
break
fi
sleep 1
- done
+ done
}
-
+
_testme(){
${TESTJAVA}/bin/java \
-cp ${_testclasses} \
$* \
- -Dcom.sun.management.jdp.port=7095 \
- -Dcom.sun.management.jdp.address=239.255.255.225 \
- JdpClient
+ -Dcom.sun.management.jdp.port=${_port} \
+ -Dcom.sun.management.jdp.address=${_ip} \
+ JdpClient
-}
+}
_jcmd(){
${TESTJAVA}/bin/jcmd JdpDoSomething $* > /dev/null 2>/dev/null
-}
+}
_echo(){
echo "$*"
echo "$*" >> ${_logname}
}
-
+
# ============= TESTS ======================================
-
+
test_01(){
-
- _echo "**** Test one ****"
+
+ _echo "**** Test one ****"
_app_start JdpUnitTest \
- -Dcom.sun.management.jdp.port=7095 \
- -Dcom.sun.management.jdp.address=239.255.255.225 \
+ -Dcom.sun.management.jdp.port=${_port} \
+ -Dcom.sun.management.jdp.address=${_ip} \
-Dcom.sun.management.jdp.pause=5
res=`_testme`
- case "${res}" in
- OK*)
+ case "${res}" in
+ OK*)
_echo "Passed"
;;
*)
@@ -155,24 +158,24 @@
esac
_app_stop
-}
+}
test_02(){
-
- _echo "**** Test two ****"
+
+ _echo "**** Test two ****"
_app_start JdpDoSomething \
- -Dcom.sun.management.jdp.port=7095 \
- -Dcom.sun.management.jdp.address=239.255.255.225 \
+ -Dcom.sun.management.jdp.port=${_port} \
+ -Dcom.sun.management.jdp.address=${_ip} \
-Dcom.sun.management.jdp.pause=5 \
- -Dcom.sun.management.jmxremote.port=4545 \
+ -Dcom.sun.management.jmxremote.port=${_jmxport} \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false
res=`_testme`
- case "${res}" in
- OK*)
+ case "${res}" in
+ OK*)
_echo "Passed"
;;
*)
@@ -181,26 +184,26 @@
esac
_app_stop
-}
+}
test_03(){
-
+
_echo "**** Test three ****"
_app_start JdpDoSomething
-
+
_jcmd ManagementAgent.start\
- jdp.port=7095 \
- jdp.address=239.255.255.225 \
+ jdp.port=${_port} \
+ jdp.address=${_ip} \
jdp.pause=5 \
- jmxremote.port=4545 \
+ jmxremote.port=${_jmxport} \
jmxremote.authenticate=false \
jmxremote.ssl=false
res=`_testme`
- case "${res}" in
- OK*)
+ case "${res}" in
+ OK*)
_echo "Passed"
;;
*)
@@ -209,7 +212,7 @@
esac
_app_stop
-}
+}
test_04(){
@@ -217,7 +220,7 @@
_app_start JdpDoSomething \
-Dcom.sun.management.jmxremote.autodiscovery=true \
- -Dcom.sun.management.jmxremote.port=4545 \
+ -Dcom.sun.management.jmxremote.port=${_jmxport} \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false
@@ -243,7 +246,7 @@
_jcmd ManagementAgent.start\
jmxremote.autodiscovery=true \
- jmxremote.port=4545 \
+ jmxremote.port=${_jmxport} \
jmxremote.authenticate=false \
jmxremote.ssl=false
@@ -279,20 +282,20 @@
#------------------------------------------------------------------------------
-# reading parameters
+# reading parameters
-for parm in "$@"
+for parm in "$@"
do
case $parm in
--verbose) _verbose=yes ;;
--jtreg) _jtreg=yes ;;
--no-compile) _compile=no ;;
--testsuite=*) _testsuite=`_echo $parm | sed "s,^--.*=\(.*\),\1,"` ;;
- *)
- echo "Undefined parameter $parm. Try --help for help"
- exit
+ *)
+ echo "Undefined parameter $parm. Try --help for help"
+ exit
;;
- esac
+ esac
done
if [ "${_compile}" = "yes" ]
@@ -325,11 +328,11 @@
cat ${_testsrc}/policy.tpl | \
sed -e "s,@_TESTCLASSES@,${_testclasses},g" -e "s,@TESTJAVA@,${TESTJAVA},g" \
> ${_policyname}
-
+
fi
-
+
# Local mode tests
for i in `echo ${_testsuite} | sed -e "s/,/ /g"`
do
- test_${i}
+ test_${i}
done
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/tools/KtabZero.java Mon Jun 03 23:23:20 2013 -0700
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import sun.security.krb5.internal.ktab.KeyTab;
+import sun.security.krb5.internal.ktab.KeyTabConstants;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+/*
+ * @test
+ * @bug 8014196
+ * @summary ktab creates a file with zero kt_vno
+ */
+public class KtabZero {
+
+ static final String NAME = "k.tab";
+
+ public static void main(String[] args) throws Exception {
+
+ // 0. Non-existing keytab
+ Files.deleteIfExists(Paths.get(NAME));
+ check(true);
+
+ // 1. Create with KeyTab
+ Files.deleteIfExists(Paths.get(NAME));
+ KeyTab.getInstance(NAME).save();
+ check(false);
+
+ // 2. Create with the tool
+ Files.deleteIfExists(Paths.get(NAME));
+ try {
+ Class ktab = Class.forName("sun.security.krb5.internal.tools.Ktab");
+ ktab.getDeclaredMethod("main", String[].class).invoke(null,
+ (Object)(("-k " + NAME + " -a me@HERE pass").split(" ")));
+ } catch (ClassNotFoundException cnfe) {
+ // Only Windows has ktab tool
+ System.out.println("No ktab tool here. Ignored.");
+ return;
+ }
+ check(false);
+ }
+
+ // Checks existence as well as kt-vno
+ static void check(boolean showBeMissing) throws Exception {
+ KeyTab kt = KeyTab.getInstance(NAME);
+ if (kt.isMissing() != showBeMissing) {
+ throw new Exception("isMissing is not " + showBeMissing);
+ }
+ Field f = KeyTab.class.getDeclaredField("kt_vno");
+ f.setAccessible(true);
+ if (f.getInt(kt) != KeyTabConstants.KRB5_KT_VNO) {
+ throw new Exception("kt_vno is " + f.getInt(kt));
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/tools/ktzero.sh Mon Jun 03 23:23:20 2013 -0700
@@ -0,0 +1,74 @@
+#
+# Copyright (c) 2013, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+# @test
+# @bug 8014196
+# @summary ktab creates a file with zero kt_vno
+# @run shell ktzero.sh
+#
+
+if [ "${TESTJAVA}" = "" ] ; then
+ JAVAC_CMD=`which javac`
+ TESTJAVA=`dirname $JAVAC_CMD`/..
+fi
+
+if [ "${TESTSRC}" = "" ] ; then
+ TESTSRC="."
+fi
+
+OS=`uname -s`
+case "$OS" in
+ CYGWIN* )
+ FS="/"
+ ;;
+ Windows_* )
+ FS="\\"
+ ;;
+ * )
+ FS="/"
+ echo "Unsupported system!"
+ exit 0;
+ ;;
+esac
+
+KEYTAB=ktzero.tmp
+
+rm $KEYTAB 2> /dev/null
+KTAB="${TESTJAVA}${FS}bin${FS}ktab -k $KEYTAB"
+
+# Listing non-existing ktab should fail
+$KTAB -l && exit 1
+
+# Can add to non-existing ktab
+$KTAB -a me@LOCAL mine || exit 2
+
+# Now can be listed
+$KTAB -l || exit 3
+
+echo ABCDEFG > $KEYTAB
+
+# Invalid keytab should fail for all commands
+$KTAB -l && exit 4
+$KTAB -a me@LOCAL mine && exit 2
+
+exit 0
--- a/jdk/test/sun/text/resources/LocaleData Thu May 30 10:58:21 2013 -0700
+++ b/jdk/test/sun/text/resources/LocaleData Mon Jun 03 23:23:20 2013 -0700
@@ -7663,3 +7663,7 @@
# bug 7114053
LocaleNames/sq/sq=shqip
+
+# bug 7074882
+FormatData/mt/MonthNames/7=Awwissu
+FormatData/mt/MonthAbbreviations/7=Aww
--- a/jdk/test/sun/text/resources/LocaleDataTest.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/test/sun/text/resources/LocaleDataTest.java Mon Jun 03 23:23:20 2013 -0700
@@ -35,7 +35,7 @@
* 6645405 6650730 6910489 6573250 6870908 6585666 6716626 6914413 6916787
* 6919624 6998391 7019267 7020960 7025837 7020583 7036905 7066203 7101495
* 7003124 7085757 7028073 7171028 7189611 8000983 7195759 8004489 8006509
- * 7114053
+ * 7114053 7074882
* @summary Verify locale data
*
*/
--- a/jdk/test/tools/launcher/Arrrghs.java Thu May 30 10:58:21 2013 -0700
+++ b/jdk/test/tools/launcher/Arrrghs.java Mon Jun 03 23:23:20 2013 -0700
@@ -24,7 +24,7 @@
/**
* @test
* @bug 5030233 6214916 6356475 6571029 6684582 6742159 4459600 6758881 6753938
- * 6894719 6968053 7151434 7146424
+ * 6894719 6968053 7151434 7146424 8007333
* @summary Argument parsing validation.
* @compile -XDignore.symbol.file Arrrghs.java
* @run main/othervm Arrrghs
@@ -310,6 +310,20 @@
checkArgumentParsing("..\\..\\", "..\\..\\");
checkArgumentParsing("../../", "../../");
checkArgumentParsing("a b\\ c", "a", "b\\", "c");
+ // 2 back-slashes
+ checkArgumentParsing("\\\\?", "\\\\?");
+ // 3 back-slashes
+ checkArgumentParsing("\\\\\\?", "\\\\\\?");
+ // 4 back-slashes
+ checkArgumentParsing("\\\\\\\\?", "\\\\\\\\?");
+ // 5 back-slashes
+ checkArgumentParsing("\\\\\\\\\\?", "\\\\\\\\\\?");
+ // 6 back-slashes
+ checkArgumentParsing("\\\\\\\\\\\\?", "\\\\\\\\\\\\?");
+
+ // more treatment of mixed slashes
+ checkArgumentParsing("f1/ f3\\ f4/", "f1/", "f3\\", "f4/");
+ checkArgumentParsing("f1/ f2\' ' f3/ f4/", "f1/", "f2\'", "'", "f3/", "f4/");
}
private void initEmptyDir(File emptyDir) throws IOException {