--- a/jdk/make/Import.gmk Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/make/Import.gmk Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2012, 2016, 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
@@ -83,20 +83,20 @@
endif
ifneq ($(OPENJDK_TARGET_OS), windows)
- ifeq ($(JVM_VARIANT_SERVER), true)
+ ifeq ($(call check-jvm-variant, server), true)
BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/server/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX)
ifneq (, $(JSIG_DEBUGINFO))
BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/server/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I))
endif
endif
- ifeq ($(JVM_VARIANT_CLIENT), true)
+ ifeq ($(call check-jvm-variant, client), true)
BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/client/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX)
ifneq (, $(JSIG_DEBUGINFO))
BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/client/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I))
endif
endif
ifneq ($(OPENJDK_TARGET_OS), macosx)
- ifeq ($(JVM_VARIANT_MINIMAL1), true)
+ ifeq ($(call check-jvm-variant, minimal), true)
BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/minimal/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX)
ifneq (,$(JSIG_DEBUGINFO))
BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/minimal/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I))
--- a/jdk/make/copy/Copy-java.base.gmk Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/make/copy/Copy-java.base.gmk Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2014, 2016, 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,7 +88,7 @@
#
# How to install jvm.cfg.
#
-ifeq ($(JVM_VARIANT_ZERO), true)
+ifeq ($(call check-jvm-variant, zero zeroshark), true)
JVMCFG_ARCH := zero
else
JVMCFG_ARCH := $(OPENJDK_TARGET_CPU_LEGACY)
@@ -99,7 +99,7 @@
else
JVMCFG_SRC := $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/conf/$(JVMCFG_ARCH)/jvm.cfg
# Allow override by ALT_JVMCFG_SRC if it exists
- JVMCFG_SRC := $(if $(wildcard $(ALT_JVMCFG_SRC)),$(ALT_JVMCFG_SRC),$(JVMCFG_SRC))
+ JVMCFG_SRC := $(if $(wildcard $(ALT_JVMCFG_SRC)),$(ALT_JVMCFG_SRC),$(JVMCFG_SRC))
endif
JVMCFG_DIR := $(LIB_DST_DIR)$(OPENJDK_TARGET_CPU_LIBDIR)
JVMCFG := $(JVMCFG_DIR)/jvm.cfg
@@ -117,12 +117,12 @@
# The main problem is deciding whether to use aliases for the VMs that are not
# present and the current position is that we add aliases for client and server, but
# not for minimal.
- CLIENT_AND_SERVER := $(and $(findstring true, $(JVM_VARIANT_SERVER)), $(findstring true, $(JVM_VARIANT_CLIENT)))
- ifeq ($(CLIENT_AND_SERVER), true)
+ CLIENT_AND_SERVER := $(call check-jvm-variant, client)+$(call check-jvm-variant, server)
+ ifeq ($(CLIENT_AND_SERVER), true+true)
COPY_JVM_CFG_FILE := true
else
# For zero, the default jvm.cfg file is sufficient
- ifeq ($(JVM_VARIANT_ZERO), true)
+ ifeq ($(call check-jvm-variant, zero zeroshark), true)
COPY_JVM_CFG_FILE := true
endif
endif
@@ -136,21 +136,21 @@
$(MKDIR) -p $(@D)
$(RM) $(@)
# Now check for other permutations
- ifeq ($(JVM_VARIANT_SERVER), true)
+ ifeq ($(call check-jvm-variant, server), true)
$(PRINTF) "-server KNOWN\n">>$(@)
$(PRINTF) "-client ALIASED_TO -server\n">>$(@)
- ifeq ($(JVM_VARIANT_MINIMAL1), true)
+ ifeq ($(call check-jvm-variant, minimal), true)
$(PRINTF) "-minimal KNOWN\n">>$(@)
endif
else
- ifeq ($(JVM_VARIANT_CLIENT), true)
+ ifeq ($(call check-jvm-variant, client), true)
$(PRINTF) "-client KNOWN\n">>$(@)
$(PRINTF) "-server ALIASED_TO -client\n">>$(@)
- ifeq ($(JVM_VARIANT_MINIMAL1), true)
+ ifeq ($(call check-jvm-variant, minimal), true)
$(PRINTF) "-minimal KNOWN\n">>$(@)
endif
else
- ifeq ($(JVM_VARIANT_MINIMAL1), true)
+ ifeq ($(call check-jvm-variant, minimal), true)
$(PRINTF) "-minimal KNOWN\n">>$(@)
$(PRINTF) "-server ALIASED_TO -minimal\n">>$(@)
$(PRINTF) "-client ALIASED_TO -minimal\n">>$(@)
--- a/jdk/make/data/fontconfig/windows.fontconfig.properties Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/make/data/fontconfig/windows.fontconfig.properties Thu Apr 21 13:37:31 2016 -0700
@@ -37,6 +37,7 @@
allfonts.chinese-hkscs=MingLiU_HKSCS
allfonts.chinese-ms950-extb=MingLiU-ExtB
allfonts.devanagari=Mangal
+allfonts.kannada=Tunga
allfonts.dingbats=Wingdings
allfonts.lucida=Lucida Sans Regular
allfonts.symbol=Symbol
@@ -239,11 +240,11 @@
sequence.fallback=lucida,symbols,\
chinese-ms950,chinese-hkscs,chinese-ms936,chinese-gb18030,\
- japanese,korean,chinese-ms950-extb,chinese-ms936-extb,georgian
+ japanese,korean,chinese-ms950-extb,chinese-ms936-extb,georgian,kannada
# Exclusion Ranges
-exclusion.alphabetic=0700-1e9f,1f00-20ab,20ad-f8ff
+exclusion.alphabetic=0700-1e9f,1f00-2017,2020-20ab,20ad-20b8,20bb-20bc,20be-f8ff
exclusion.chinese-gb18030=0390-03d6,2200-22ef,2701-27be
exclusion.hebrew=0041-005a,0060-007a,007f-00ff,20ac-20ac
@@ -295,6 +296,7 @@
filename.Lucida_Sans_Regular=LucidaSansRegular.ttf
filename.Mangal=MANGAL.TTF
+filename.Tunga=TUNGA.TTF
filename.Symbol=SYMBOL.TTF
filename.Wingdings=WINGDING.TTF
--- a/jdk/make/lib/Awt2dLibraries.gmk Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/make/lib/Awt2dLibraries.gmk Thu Apr 21 13:37:31 2016 -0700
@@ -375,6 +375,7 @@
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) $(LIBAWT_XAWT_CFLAGS) \
$(X_CFLAGS), \
+ WARNINGS_AS_ERRORS_xlc := false, \
DISABLED_WARNINGS_gcc := type-limits pointer-to-int-cast \
deprecated-declarations unused-result maybe-uninitialized format \
format-security int-to-pointer-cast parentheses, \
@@ -587,6 +588,7 @@
$(CUPS_CFLAGS) \
$(X_CFLAGS) \
$(LIBAWT_HEADLESS_CFLAGS), \
+ DISABLED_WARNINGS_xlc := 1506-356, \
DISABLED_WARNINGS_gcc := maybe-uninitialized int-to-pointer-cast, \
DISABLED_WARNINGS_solstudio := E_DECLARATION_IN_CODE \
E_EMPTY_TRANSLATION_UNIT, \
@@ -603,6 +605,10 @@
OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libawt_headless, \
))
+ # AIX warning explanation:
+ # 1506-356 : (W) Compilation unit is empty.
+ # This happens during the headless build
+
$(BUILD_LIBAWT_HEADLESS): $(BUILD_LIBAWT)
TARGETS += $(BUILD_LIBAWT_HEADLESS)
@@ -700,6 +706,7 @@
CXXFLAGS := $(CXXFLAGS_JDKLIB) $(LIBFONTMANAGER_CFLAGS), \
OPTIMIZATION := $(LIBFONTMANAGER_OPTIMIZATION), \
CFLAGS_windows = -DCC_NOEX, \
+ WARNINGS_AS_ERRORS_xlc := false, \
DISABLED_WARNINGS_gcc := sign-compare int-to-pointer-cast \
type-limits missing-field-initializers, \
DISABLED_WARNINGS_CXX_gcc := reorder delete-non-virtual-dtor strict-overflow \
--- a/jdk/make/lib/CoreLibraries.gmk Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/make/lib/CoreLibraries.gmk Thu Apr 21 13:37:31 2016 -0700
@@ -146,6 +146,7 @@
$(LIBJAVA_CFLAGS), \
System.c_CFLAGS := $(VERSION_CFLAGS), \
jdk_util.c_CFLAGS := $(VERSION_CFLAGS), \
+ WARNINGS_AS_ERRORS_xlc := false, \
DISABLED_WARNINGS_gcc := unused-result, \
DISABLED_WARNINGS_solstudio := E_STATEMENT_NOT_REACHED, \
MAPFILE := $(LIBJAVA_MAPFILE), \
@@ -289,7 +290,7 @@
LIBJLI_CFLAGS := $(CFLAGS_JDKLIB)
-ifeq ($(JVM_VARIANT_ZERO), true)
+ifeq ($(call check-jvm-variant, zero zeroshark), true)
ERGO_FAMILY := zero
else
ifeq ($(OPENJDK_TARGET_CPU_ARCH), x86)
--- a/jdk/make/lib/NioLibraries.gmk Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/make/lib/NioLibraries.gmk Thu Apr 21 13:37:31 2016 -0700
@@ -70,6 +70,7 @@
SRC := $(BUILD_LIBNIO_SRC), \
EXCLUDE_FILES := $(BUILD_LIBNIO_EXFILES), \
OPTIMIZATION := HIGH, \
+ WARNINGS_AS_ERRORS_xlc := false, \
CFLAGS := $(CFLAGS_JDKLIB) \
$(BUILD_LIBNIO_CFLAGS), \
MAPFILE := $(BUILD_LIBNIO_MAPFILE), \
--- a/jdk/make/mapfiles/libjava/mapfile-vers Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/make/mapfiles/libjava/mapfile-vers Thu Apr 21 13:37:31 2016 -0700
@@ -139,8 +139,7 @@
Java_java_lang_Double_doubleToRawLongBits;
Java_java_lang_Float_intBitsToFloat;
Java_java_lang_Float_floatToRawIntBits;
- Java_java_lang_StackFrameInfo_fillInStackFrames;
- Java_java_lang_StackFrameInfo_setMethodInfo;
+ Java_java_lang_StackFrameInfo_toStackTraceElement0;
Java_java_lang_StackStreamFactory_checkStackWalkModes;
Java_java_lang_StackStreamFactory_00024AbstractStackWalker_callStackWalk;
Java_java_lang_StackStreamFactory_00024AbstractStackWalker_fetchStackFrames;
--- a/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystemProvider.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystemProvider.java Thu Apr 21 13:37:31 2016 -0700
@@ -102,8 +102,8 @@
@Override
FileTypeDetector getFileTypeDetector() {
- Path userMimeTypes = Paths.get(AccessController.doPrivileged(
- new GetPropertyAction("user.home")), ".mime.types");
+ String userHome = GetPropertyAction.getProperty("user.home");
+ Path userMimeTypes = Paths.get(userHome, ".mime.types");
Path etcMimeTypes = Paths.get("/etc/mime.types");
return chain(new GioFileTypeDetector(),
--- a/jdk/src/java.base/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java Thu Apr 21 13:37:31 2016 -0700
@@ -32,9 +32,9 @@
package sun.nio.ch;
import java.io.IOException;
-import java.io.FileDescriptor;
import java.util.Iterator;
import java.util.LinkedList;
+import sun.security.action.GetPropertyAction;
/*
* struct kevent { // 32-bit 64-bit
@@ -84,10 +84,8 @@
static {
IOUtil.load();
initStructSizes();
- String datamodel = java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("sun.arch.data.model")
- );
- is64bit = datamodel.equals("64");
+ String datamodel = GetPropertyAction.getProperty("sun.arch.data.model");
+ is64bit = "64".equals(datamodel);
}
KQueueArrayWrapper() {
--- a/jdk/src/java.base/macosx/classes/sun/nio/fs/MacOSXFileSystemProvider.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/macosx/classes/sun/nio/fs/MacOSXFileSystemProvider.java Thu Apr 21 13:37:31 2016 -0700
@@ -28,7 +28,6 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.spi.FileTypeDetector;
-import java.security.AccessController;
import sun.security.action.GetPropertyAction;
/**
@@ -47,8 +46,8 @@
@Override
FileTypeDetector getFileTypeDetector() {
- Path userMimeTypes = Paths.get(AccessController.doPrivileged(
- new GetPropertyAction("user.home")), ".mime.types");
+ Path userMimeTypes = Paths.get(
+ GetPropertyAction.getProperty("user.home"), ".mime.types");
return chain(new MimeTypesFileTypeDetector(userMimeTypes),
new UTIFileTypeDetector());
--- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java Thu Apr 21 13:37:31 2016 -0700
@@ -512,11 +512,17 @@
byte[] sOut = new byte[s.length];
GCTR gctrForSToTag = new GCTR(embeddedCipher, this.preCounterBlock);
gctrForSToTag.doFinal(s, 0, s.length, sOut, 0);
+
+ // check entire authentication tag for time-consistency
+ int mismatch = 0;
for (int i = 0; i < tagLenBytes; i++) {
- if (tag[i] != sOut[i]) {
- throw new AEADBadTagException("Tag mismatch!");
- }
+ mismatch |= tag[i] ^ sOut[i];
}
+
+ if (mismatch != 0) {
+ throw new AEADBadTagException("Tag mismatch!");
+ }
+
return len;
}
--- a/jdk/src/java.base/share/classes/java/io/DataInput.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/io/DataInput.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, 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
@@ -182,10 +182,11 @@
* not all bytes of {@code b} have been
* updated with data from the input stream.
*
- * @param b the buffer into which the data is read.
- * @exception EOFException if this stream reaches the end before reading
- * all the bytes.
- * @exception IOException if an I/O error occurs.
+ * @param b the buffer into which the data is read.
+ * @throws NullPointerException if {@code b} is {@code null}.
+ * @throws EOFException if this stream reaches the end before reading
+ * all the bytes.
+ * @throws IOException if an I/O error occurs.
*/
void readFully(byte b[]) throws IOException;
@@ -226,12 +227,16 @@
* and so on. The number of bytes read is,
* at most, equal to {@code len}.
*
- * @param b the buffer into which the data is read.
- * @param off an int specifying the offset into the data.
- * @param len an int specifying the number of bytes to read.
- * @exception EOFException if this stream reaches the end before reading
- * all the bytes.
- * @exception IOException if an I/O error occurs.
+ * @param b the buffer into which the data is read.
+ * @param off an int specifying the offset in the data array {@code b}.
+ * @param len an int specifying the number of bytes to read.
+ * @throws NullPointerException if {@code b} is {@code null}.
+ * @throws IndexOutOfBoundsException if {@code off} is negative,
+ * {@code len} is negative, or {@code len} is greater than
+ * {@code b.length - off}.
+ * @throws EOFException if this stream reaches the end before reading
+ * all the bytes.
+ * @throws IOException if an I/O error occurs.
*/
void readFully(byte b[], int off, int len) throws IOException;
--- a/jdk/src/java.base/share/classes/java/io/DataInputStream.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/io/DataInputStream.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2016, 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
@@ -150,38 +150,43 @@
}
/**
- * See the general contract of the <code>readFully</code>
- * method of <code>DataInput</code>.
+ * See the general contract of the {@code readFully}
+ * method of {@code DataInput}.
* <p>
* Bytes
* for this operation are read from the contained
* input stream.
*
- * @param b the buffer into which the data is read.
- * @exception EOFException if this input stream reaches the end before
- * reading all the bytes.
- * @exception IOException the stream has been closed and the contained
- * input stream does not support reading after close, or
- * another I/O error occurs.
- * @see java.io.FilterInputStream#in
+ * @param b the buffer into which the data is read.
+ * @throws NullPointerException if {@code b} is {@code null}.
+ * @throws EOFException if this input stream reaches the end before
+ * reading all the bytes.
+ * @throws IOException the stream has been closed and the contained
+ * input stream does not support reading after close, or
+ * another I/O error occurs.
+ * @see java.io.FilterInputStream#in
*/
public final void readFully(byte b[]) throws IOException {
readFully(b, 0, b.length);
}
/**
- * See the general contract of the <code>readFully</code>
- * method of <code>DataInput</code>.
+ * See the general contract of the {@code readFully}
+ * method of {@code DataInput}.
* <p>
* Bytes
* for this operation are read from the contained
* input stream.
*
* @param b the buffer into which the data is read.
- * @param off the start offset of the data.
+ * @param off the start offset in the data array {@code b}.
* @param len the number of bytes to read.
+ * @exception NullPointerException if {@code b} is {@code null}.
+ * @exception IndexOutOfBoundsException if {@code off} is negative,
+ * {@code len} is negative, or {@code len} is greater than
+ * {@code b.length - off}.
* @exception EOFException if this input stream reaches the end before
- * reading all the bytes.
+ * reading all the bytes.
* @exception IOException the stream has been closed and the contained
* input stream does not support reading after close, or
* another I/O error occurs.
--- a/jdk/src/java.base/share/classes/java/io/File.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/io/File.java Thu Apr 21 13:37:31 2016 -0700
@@ -31,7 +31,6 @@
import java.net.URISyntaxException;
import java.util.List;
import java.util.ArrayList;
-import java.security.AccessController;
import java.security.SecureRandom;
import java.nio.file.Path;
import java.nio.file.FileSystems;
@@ -1896,8 +1895,8 @@
private TempDirectory() { }
// temporary directory location
- private static final File tmpdir = new File(AccessController
- .doPrivileged(new GetPropertyAction("java.io.tmpdir")));
+ private static final File tmpdir = new File(
+ GetPropertyAction.getProperty("java.io.tmpdir"));
static File location() {
return tmpdir;
}
--- a/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java Thu Apr 21 13:37:31 2016 -0700
@@ -40,6 +40,9 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import static java.io.ObjectStreamClass.processQueue;
+import jdk.internal.misc.JavaObjectInputStreamAccess;
+import jdk.internal.misc.ObjectStreamClassValidator;
+import jdk.internal.misc.SharedSecrets;
import jdk.internal.misc.Unsafe;
import sun.reflect.misc.ReflectUtil;
@@ -853,10 +856,14 @@
* exactly 'length' bytes.
*
* @param buf the buffer into which the data is read
- * @param off the start offset of the data
+ * @param off the start offset in the destination array {@code buf}
* @param len the maximum number of bytes read
* @return the actual number of bytes read, -1 is returned when the end of
* the stream is reached.
+ * @throws NullPointerException if {@code buf} is {@code null}.
+ * @throws IndexOutOfBoundsException if {@code off} is negative,
+ * {@code len} is negative, or {@code len} is greater than
+ * {@code buf.length - off}.
* @throws IOException If an I/O error has occurred.
* @see java.io.DataInputStream#readFully(byte[],int,int)
*/
@@ -1014,6 +1021,7 @@
* Reads bytes, blocking until all bytes are read.
*
* @param buf the buffer into which the data is read
+ * @throws NullPointerException If {@code buf} is {@code null}.
* @throws EOFException If end of file is reached.
* @throws IOException If other I/O error has occurred.
*/
@@ -1025,8 +1033,12 @@
* Reads bytes, blocking until all bytes are read.
*
* @param buf the buffer into which the data is read
- * @param off the start offset of the data
+ * @param off the start offset into the data array {@code buf}
* @param len the maximum number of bytes to read
+ * @throws NullPointerException If {@code buf} is {@code null}.
+ * @throws IndexOutOfBoundsException If {@code off} is negative,
+ * {@code len} is negative, or {@code len} is greater than
+ * {@code buf.length - off}.
* @throws EOFException If end of file is reached.
* @throws IOException If other I/O error has occurred.
*/
@@ -1509,23 +1521,28 @@
throws IOException
{
byte tc = bin.peekByte();
+ ObjectStreamClass descriptor;
switch (tc) {
case TC_NULL:
- return (ObjectStreamClass) readNull();
-
+ descriptor = (ObjectStreamClass) readNull();
+ break;
case TC_REFERENCE:
- return (ObjectStreamClass) readHandle(unshared);
-
+ descriptor = (ObjectStreamClass) readHandle(unshared);
+ break;
case TC_PROXYCLASSDESC:
- return readProxyDesc(unshared);
-
+ descriptor = readProxyDesc(unshared);
+ break;
case TC_CLASSDESC:
- return readNonProxyDesc(unshared);
-
+ descriptor = readNonProxyDesc(unshared);
+ break;
default:
throw new StreamCorruptedException(
String.format("invalid type code: %02X", tc));
}
+ if (descriptor != null) {
+ validateDescriptor(descriptor);
+ }
+ return descriptor;
}
private boolean isCustomSubclass() {
@@ -1915,6 +1932,8 @@
if (obj == null || handles.lookupException(passHandle) != null) {
defaultReadFields(null, slotDesc); // skip field values
} else if (slotDesc.hasReadObjectMethod()) {
+ ThreadDeath t = null;
+ boolean reset = false;
SerialCallbackContext oldContext = curContext;
if (oldContext != null)
oldContext.check();
@@ -1933,10 +1952,19 @@
*/
handles.markException(passHandle, ex);
} finally {
- curContext.setUsed();
- if (oldContext!= null)
- oldContext.check();
- curContext = oldContext;
+ do {
+ try {
+ curContext.setUsed();
+ if (oldContext!= null)
+ oldContext.check();
+ curContext = oldContext;
+ reset = true;
+ } catch (ThreadDeath x) {
+ t = x; // defer until reset is true
+ }
+ } while (!reset);
+ if (t != null)
+ throw t;
}
/*
@@ -3647,4 +3675,20 @@
}
}
+ private void validateDescriptor(ObjectStreamClass descriptor) {
+ ObjectStreamClassValidator validating = validator;
+ if (validating != null) {
+ validating.validateDescriptor(descriptor);
+ }
+ }
+
+ // controlled access to ObjectStreamClassValidator
+ private volatile ObjectStreamClassValidator validator;
+
+ private static void setValidator(ObjectInputStream ois, ObjectStreamClassValidator validator) {
+ ois.validator = validator;
+ }
+ static {
+ SharedSecrets.setJavaObjectInputStreamAccess(ObjectInputStream::setValidator);
+ }
}
--- a/jdk/src/java.base/share/classes/java/io/RandomAccessFile.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/io/RandomAccessFile.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2016, 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
@@ -418,10 +418,11 @@
* read. This method blocks until the requested number of bytes are
* read, the end of the stream is detected, or an exception is thrown.
*
- * @param b the buffer into which the data is read.
- * @exception EOFException if this file reaches the end before reading
- * all the bytes.
- * @exception IOException if an I/O error occurs.
+ * @param b the buffer into which the data is read.
+ * @throws NullPointerException if {@code b} is {@code null}.
+ * @throws EOFException if this file reaches the end before reading
+ * all the bytes.
+ * @throws IOException if an I/O error occurs.
*/
public final void readFully(byte b[]) throws IOException {
readFully(b, 0, b.length);
@@ -434,12 +435,16 @@
* read. This method blocks until the requested number of bytes are
* read, the end of the stream is detected, or an exception is thrown.
*
- * @param b the buffer into which the data is read.
- * @param off the start offset of the data.
- * @param len the number of bytes to read.
- * @exception EOFException if this file reaches the end before reading
- * all the bytes.
- * @exception IOException if an I/O error occurs.
+ * @param b the buffer into which the data is read.
+ * @param off the start offset into the data array {@code b}.
+ * @param len the number of bytes to read.
+ * @throws NullPointerException if {@code b} is {@code null}.
+ * @throws IndexOutOfBoundsException if {@code off} is negative,
+ * {@code len} is negative, or {@code len} is greater than
+ * {@code b.length - off}.
+ * @throws EOFException if this file reaches the end before reading
+ * all the bytes.
+ * @throws IOException if an I/O error occurs.
*/
public final void readFully(byte b[], int off, int len) throws IOException {
int n = 0;
--- a/jdk/src/java.base/share/classes/java/lang/Boolean.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/Boolean.java Thu Apr 21 13:37:31 2016 -0700
@@ -79,13 +79,16 @@
* Allocates a {@code Boolean} object representing the
* {@code value} argument.
*
- * <p><b>Note: It is rarely appropriate to use this constructor.
- * Unless a <i>new</i> instance is required, the static factory
- * {@link #valueOf(boolean)} is generally a better choice. It is
- * likely to yield significantly better space and time performance.</b>
+ * @param value the value of the {@code Boolean}.
*
- * @param value the value of the {@code Boolean}.
+ * @deprecated
+ * It is rarely appropriate to use this constructor. The static factory
+ * {@link #valueOf(boolean)} is generally a better choice, as it is
+ * likely to yield significantly better space and time performance.
+ * Also consider using the final fields {@link #TRUE} and {@link #FALSE}
+ * if possible.
*/
+ @Deprecated(since="9")
public Boolean(boolean value) {
this.value = value;
}
@@ -94,15 +97,18 @@
* Allocates a {@code Boolean} object representing the value
* {@code true} if the string argument is not {@code null}
* and is equal, ignoring case, to the string {@code "true"}.
- * Otherwise, allocate a {@code Boolean} object representing the
- * value {@code false}. Examples:<p>
- * {@code new Boolean("True")} produces a {@code Boolean} object
- * that represents {@code true}.<br>
- * {@code new Boolean("yes")} produces a {@code Boolean} object
- * that represents {@code false}.
+ * Otherwise, allocates a {@code Boolean} object representing the
+ * value {@code false}.
*
* @param s the string to be converted to a {@code Boolean}.
+ *
+ * @deprecated
+ * It is rarely appropriate to use this constructor.
+ * Use {@link #parseBoolean(String)} to convert a string to a
+ * {@code boolean} primitive, or use {@link #valueOf(String)}
+ * to convert a string to a {@code Boolean} object.
*/
+ @Deprecated(since="9")
public Boolean(String s) {
this(parseBoolean(s));
}
--- a/jdk/src/java.base/share/classes/java/lang/Byte.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/Byte.java Thu Apr 21 13:37:31 2016 -0700
@@ -297,7 +297,13 @@
*
* @param value the value to be represented by the
* {@code Byte}.
+ *
+ * @deprecated
+ * It is rarely appropriate to use this constructor. The static factory
+ * {@link #valueOf(byte)} is generally a better choice, as it is
+ * likely to yield significantly better space and time performance.
*/
+ @Deprecated(since="9")
public Byte(byte value) {
this.value = value;
}
@@ -311,10 +317,16 @@
*
* @param s the {@code String} to be converted to a
* {@code Byte}
- * @throws NumberFormatException If the {@code String}
+ * @throws NumberFormatException if the {@code String}
* does not contain a parsable {@code byte}.
- * @see java.lang.Byte#parseByte(java.lang.String, int)
+ *
+ * @deprecated
+ * It is rarely appropriate to use this constructor.
+ * Use {@link #parseByte(String)} to convert a string to a
+ * {@code byte} primitive, or use {@link #valueOf(String)}
+ * to convert a string to a {@code Byte} object.
*/
+ @Deprecated(since="9")
public Byte(String s) throws NumberFormatException {
this.value = parseByte(s, 10);
}
--- a/jdk/src/java.base/share/classes/java/lang/Character.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/Character.java Thu Apr 21 13:37:31 2016 -0700
@@ -1256,14 +1256,14 @@
new UnicodeBlock("SPECIALS");
/**
- * @deprecated As of J2SE 5, use {@link #HIGH_SURROGATES},
- * {@link #HIGH_PRIVATE_USE_SURROGATES}, and
- * {@link #LOW_SURROGATES}. These new constants match
- * the block definitions of the Unicode Standard.
- * The {@link #of(char)} and {@link #of(int)} methods
- * return the new constants, not SURROGATES_AREA.
- */
- @Deprecated
+ * @deprecated
+ * Instead of {@code SURROGATES_AREA}, use {@link #HIGH_SURROGATES},
+ * {@link #HIGH_PRIVATE_USE_SURROGATES}, and {@link #LOW_SURROGATES}.
+ * These constants match the block definitions of the Unicode Standard.
+ * The {@link #of(char)} and {@link #of(int)} methods return the
+ * standard constants.
+ */
+ @Deprecated(since="1.5")
public static final UnicodeBlock SURROGATES_AREA =
new UnicodeBlock("SURROGATES_AREA");
@@ -7451,7 +7451,13 @@
*
* @param value the value to be represented by the
* {@code Character} object.
- */
+ *
+ * @deprecated
+ * It is rarely appropriate to use this constructor. The static factory
+ * {@link #valueOf(char)} is generally a better choice, as it is
+ * likely to yield significantly better space and time performance.
+ */
+ @Deprecated(since="9")
public Character(char value) {
this.value = value;
}
@@ -8799,7 +8805,7 @@
* @since 1.0.2
* @deprecated Replaced by isJavaIdentifierStart(char).
*/
- @Deprecated
+ @Deprecated(since="1.1")
public static boolean isJavaLetter(char ch) {
return isJavaIdentifierStart(ch);
}
@@ -8835,7 +8841,7 @@
* @since 1.0.2
* @deprecated Replaced by isJavaIdentifierPart(char).
*/
- @Deprecated
+ @Deprecated(since="1.1")
public static boolean isJavaLetterOrDigit(char ch) {
return isJavaIdentifierPart(ch);
}
@@ -9580,7 +9586,7 @@
* @see Character#isWhitespace(char)
* @deprecated Replaced by isWhitespace(char).
*/
- @Deprecated
+ @Deprecated(since="1.1")
public static boolean isSpace(char ch) {
return (ch <= 0x0020) &&
(((((1L << 0x0009) |
--- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java Thu Apr 21 13:37:31 2016 -0700
@@ -727,7 +727,7 @@
* @deprecated Replaced by {@link #defineClass(String, byte[], int, int)
* defineClass(String, byte[], int, int)}
*/
- @Deprecated
+ @Deprecated(since="1.1")
protected final Class<?> defineClass(byte[] b, int off, int len)
throws ClassFormatError
{
@@ -817,6 +817,9 @@
if (!checkName(name))
throw new NoClassDefFoundError("IllegalName: " + name);
+ // Note: Checking logic in java.lang.invoke.MemberName.checkForTypeAlias
+ // relies on the fact that spoofing is impossible if a class has a name
+ // of the form "java.*"
if ((name != null) && name.startsWith("java.")
&& this != getBuiltinPlatformClassLoader()) {
throw new SecurityException
@@ -2012,7 +2015,7 @@
*
* @since 1.2
*/
- @Deprecated
+ @Deprecated(since="9")
protected Package getPackage(String name) {
Package pkg = getDefinedPackage(name);
if (pkg == null) {
--- a/jdk/src/java.base/share/classes/java/lang/Double.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/Double.java Thu Apr 21 13:37:31 2016 -0700
@@ -589,7 +589,13 @@
* represents the primitive {@code double} argument.
*
* @param value the value to be represented by the {@code Double}.
+ *
+ * @deprecated
+ * It is rarely appropriate to use this constructor. The static factory
+ * {@link #valueOf(double)} is generally a better choice, as it is
+ * likely to yield significantly better space and time performance.
*/
+ @Deprecated(since="9")
public Double(double value) {
this.value = value;
}
@@ -601,10 +607,16 @@
* {@code double} value as if by the {@code valueOf} method.
*
* @param s a string to be converted to a {@code Double}.
- * @throws NumberFormatException if the string does not contain a
+ * @throws NumberFormatException if the string does not contain a
* parsable number.
- * @see java.lang.Double#valueOf(java.lang.String)
+ *
+ * @deprecated
+ * It is rarely appropriate to use this constructor.
+ * Use {@link #parseDouble(String)} to convert a string to a
+ * {@code double} primitive, or use {@link #valueOf(String)}
+ * to convert a string to a {@code Double} object.
*/
+ @Deprecated(since="9")
public Double(String s) throws NumberFormatException {
value = parseDouble(s);
}
--- a/jdk/src/java.base/share/classes/java/lang/Float.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/Float.java Thu Apr 21 13:37:31 2016 -0700
@@ -502,7 +502,13 @@
* represents the primitive {@code float} argument.
*
* @param value the value to be represented by the {@code Float}.
+ *
+ * @deprecated
+ * It is rarely appropriate to use this constructor. The static factory
+ * {@link #valueOf(float)} is generally a better choice, as it is
+ * likely to yield significantly better space and time performance.
*/
+ @Deprecated(since="9")
public Float(float value) {
this.value = value;
}
@@ -512,7 +518,13 @@
* represents the argument converted to type {@code float}.
*
* @param value the value to be represented by the {@code Float}.
+ *
+ * @deprecated
+ * It is rarely appropriate to use this constructor. Instead, use the
+ * static factory method {@link #valueOf(float)} method as follows:
+ * {@code Float.valueOf((float)value)}.
*/
+ @Deprecated(since="9")
public Float(double value) {
this.value = (float)value;
}
@@ -523,11 +535,17 @@
* represented by the string. The string is converted to a
* {@code float} value as if by the {@code valueOf} method.
*
- * @param s a string to be converted to a {@code Float}.
- * @throws NumberFormatException if the string does not contain a
- * parsable number.
- * @see java.lang.Float#valueOf(java.lang.String)
+ * @param s a string to be converted to a {@code Float}.
+ * @throws NumberFormatException if the string does not contain a
+ * parsable number.
+ *
+ * @deprecated
+ * It is rarely appropriate to use this constructor.
+ * Use {@link #parseFloat(String)} to convert a string to a
+ * {@code float} primitive, or use {@link #valueOf(String)}
+ * to convert a string to a {@code Float} object.
*/
+ @Deprecated(since="9")
public Float(String s) throws NumberFormatException {
value = parseFloat(s);
}
--- a/jdk/src/java.base/share/classes/java/lang/Integer.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/Integer.java Thu Apr 21 13:37:31 2016 -0700
@@ -1106,7 +1106,13 @@
*
* @param value the value to be represented by the
* {@code Integer} object.
+ *
+ * @deprecated
+ * It is rarely appropriate to use this constructor. The static factory
+ * {@link #valueOf(int)} is generally a better choice, as it is
+ * likely to yield significantly better space and time performance.
*/
+ @Deprecated(since="9")
public Integer(int value) {
this.value = value;
}
@@ -1118,12 +1124,17 @@
* {@code int} value in exactly the manner used by the
* {@code parseInt} method for radix 10.
*
- * @param s the {@code String} to be converted to an
- * {@code Integer}.
- * @exception NumberFormatException if the {@code String} does not
- * contain a parsable integer.
- * @see java.lang.Integer#parseInt(java.lang.String, int)
+ * @param s the {@code String} to be converted to an {@code Integer}.
+ * @throws NumberFormatException if the {@code String} does not
+ * contain a parsable integer.
+ *
+ * @deprecated
+ * It is rarely appropriate to use this constructor.
+ * Use {@link #parseInt(String)} to convert a string to a
+ * {@code int} primitive, or use {@link #valueOf(String)}
+ * to convert a string to an {@code Integer} object.
*/
+ @Deprecated(since="9")
public Integer(String s) throws NumberFormatException {
this.value = parseInt(s, 10);
}
--- a/jdk/src/java.base/share/classes/java/lang/Long.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/Long.java Thu Apr 21 13:37:31 2016 -0700
@@ -1340,7 +1340,13 @@
*
* @param value the value to be represented by the
* {@code Long} object.
+ *
+ * @deprecated
+ * It is rarely appropriate to use this constructor. The static factory
+ * {@link #valueOf(long)} is generally a better choice, as it is
+ * likely to yield significantly better space and time performance.
*/
+ @Deprecated(since="9")
public Long(long value) {
this.value = value;
}
@@ -1356,8 +1362,14 @@
* {@code Long}.
* @throws NumberFormatException if the {@code String} does not
* contain a parsable {@code long}.
- * @see java.lang.Long#parseLong(java.lang.String, int)
+ *
+ * @deprecated
+ * It is rarely appropriate to use this constructor.
+ * Use {@link #parseLong(String)} to convert a string to a
+ * {@code long} primitive, or use {@link #valueOf(String)}
+ * to convert a string to a {@code Long} object.
*/
+ @Deprecated(since="9")
public Long(String s) throws NumberFormatException {
this.value = parseLong(s, 10);
}
--- a/jdk/src/java.base/share/classes/java/lang/Package.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/Package.java Thu Apr 21 13:37:31 2016 -0700
@@ -333,7 +333,7 @@
* @see ClassLoader#getDefinedPackage
*/
@CallerSensitive
- @Deprecated
+ @Deprecated(since="9")
@SuppressWarnings("deprecation")
public static Package getPackage(String name) {
ClassLoader l = ClassLoader.getClassLoader(Reflection.getCallerClass());
--- a/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java Thu Apr 21 13:37:31 2016 -0700
@@ -30,13 +30,12 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.nio.channels.Pipe;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
+import sun.security.action.GetPropertyAction;
+
/**
* This class is used to create operating system processes.
*
@@ -468,11 +467,9 @@
* @since 1.7
*/
public abstract static class Redirect {
- private static final File NULL_FILE = AccessController.doPrivileged(
- (PrivilegedAction<File>) () -> {
- return new File((System.getProperty("os.name")
- .startsWith("Windows") ? "NUL" : "/dev/null"));
- }
+ private static final File NULL_FILE = new File(
+ (GetPropertyAction.getProperty("os.name")
+ .startsWith("Windows") ? "NUL" : "/dev/null")
);
/**
--- a/jdk/src/java.base/share/classes/java/lang/Runtime.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/Runtime.java Thu Apr 21 13:37:31 2016 -0700
@@ -289,6 +289,7 @@
* finalizers being called on live objects while other threads are
* concurrently manipulating those objects, resulting in erratic
* behavior or deadlock.
+ * This method is subject to removal in a future version of Java SE.
*
* @throws SecurityException
* if a security manager exists and its {@code checkExit}
@@ -299,7 +300,7 @@
* @see java.lang.SecurityManager#checkExit(int)
* @since 1.1
*/
- @Deprecated
+ @Deprecated(since="1.2", forRemoval=true)
public static void runFinalizersOnExit(boolean value) {
SecurityManager security = System.getSecurityManager();
if (security != null) {
@@ -894,8 +895,9 @@
* stream in the local encoding into a character stream in Unicode is via
* the {@code InputStreamReader} and {@code BufferedReader}
* classes.
+ * This method is subject to removal in a future version of Java SE.
*/
- @Deprecated
+ @Deprecated(since="1.1", forRemoval=true)
public InputStream getLocalizedInputStream(InputStream in) {
return in;
}
@@ -915,6 +917,7 @@
* Unicode character stream into a byte stream in the local encoding is via
* the {@code OutputStreamWriter}, {@code BufferedWriter}, and
* {@code PrintWriter} classes.
+ * This method is subject to removal in a future version of Java SE.
*
* @param out OutputStream to localize
* @return a localized output stream
@@ -923,7 +926,7 @@
* @see java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream)
* @see java.io.PrintWriter#PrintWriter(java.io.OutputStream)
*/
- @Deprecated
+ @Deprecated(since="1.1", forRemoval=true)
public OutputStream getLocalizedOutputStream(OutputStream out) {
return out;
}
--- a/jdk/src/java.base/share/classes/java/lang/SecurityManager.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/SecurityManager.java Thu Apr 21 13:37:31 2016 -0700
@@ -229,7 +229,7 @@
* It is recommended that the <code>checkPermission</code>
* call be used instead.
*/
- @Deprecated
+ @Deprecated(since="1.2")
protected boolean inCheck;
/*
@@ -262,7 +262,7 @@
* It is recommended that the <code>checkPermission</code>
* call be used instead.
*/
- @Deprecated
+ @Deprecated(since="1.2")
public boolean getInCheck() {
return inCheck;
}
@@ -345,7 +345,7 @@
* @see java.lang.ClassLoader#getSystemClassLoader() getSystemClassLoader
* @see #checkPermission(java.security.Permission) checkPermission
*/
- @Deprecated
+ @Deprecated(since="1.2")
protected ClassLoader currentClassLoader() {
ClassLoader cl = currentClassLoader0();
if ((cl != null) && hasAllPermission())
@@ -391,7 +391,7 @@
* @see java.lang.ClassLoader#getSystemClassLoader() getSystemClassLoader
* @see #checkPermission(java.security.Permission) checkPermission
*/
- @Deprecated
+ @Deprecated(since="1.2")
protected Class<?> currentLoadedClass() {
Class<?> c = currentLoadedClass0();
if ((c != null) && hasAllPermission())
@@ -411,7 +411,7 @@
* call be used instead.
*
*/
- @Deprecated
+ @Deprecated(since="1.2")
protected native int classDepth(String name);
/**
@@ -449,7 +449,7 @@
* @see java.lang.ClassLoader#getSystemClassLoader() getSystemClassLoader
* @see #checkPermission(java.security.Permission) checkPermission
*/
- @Deprecated
+ @Deprecated(since="1.2")
protected int classLoaderDepth() {
int depth = classLoaderDepth0();
if (depth != -1) {
@@ -474,7 +474,7 @@
* It is recommended that the <code>checkPermission</code>
* call be used instead.
*/
- @Deprecated
+ @Deprecated(since="1.2")
protected boolean inClass(String name) {
return classDepth(name) >= 0;
}
@@ -491,7 +491,7 @@
* call be used instead.
* @see #currentClassLoader() currentClassLoader
*/
- @Deprecated
+ @Deprecated(since="1.2")
protected boolean inClassLoader() {
return currentClassLoader() != null;
}
@@ -1217,7 +1217,7 @@
* @deprecated Use #checkPermission(java.security.Permission) instead
* @see #checkPermission(java.security.Permission) checkPermission
*/
- @Deprecated
+ @Deprecated(since="1.4")
public void checkMulticast(InetAddress maddr, byte ttl) {
String host = maddr.getHostAddress();
if (!host.startsWith("[") && host.indexOf(':') != -1) {
@@ -1297,9 +1297,10 @@
* was trusted to bring up a top-level window. The method has been
* obsoleted and code should instead use {@link #checkPermission}
* to check {@code AWTPermission("showWindowWithoutWarningBanner")}.
+ * This method is subject to removal in a future version of Java SE.
* @see #checkPermission(java.security.Permission) checkPermission
*/
- @Deprecated
+ @Deprecated(since="1.8", forRemoval=true)
public boolean checkTopLevelWindow(Object window) {
if (window == null) {
throw new NullPointerException("window can't be null");
@@ -1340,9 +1341,10 @@
* thread could access the system clipboard. The method has been
* obsoleted and code should instead use {@link #checkPermission}
* to check {@code AWTPermission("accessClipboard")}.
+ * This method is subject to removal in a future version of Java SE.
* @see #checkPermission(java.security.Permission) checkPermission
*/
- @Deprecated
+ @Deprecated(since="1.8", forRemoval=true)
public void checkSystemClipboardAccess() {
checkPermission(SecurityConstants.ALL_PERMISSION);
}
@@ -1358,9 +1360,10 @@
* thread could access the AWT event queue. The method has been
* obsoleted and code should instead use {@link #checkPermission}
* to check {@code AWTPermission("accessEventQueue")}.
+ * This method is subject to removal in a future version of Java SE.
* @see #checkPermission(java.security.Permission) checkPermission
*/
- @Deprecated
+ @Deprecated(since="1.8", forRemoval=true)
public void checkAwtEventQueueAccess() {
checkPermission(SecurityConstants.ALL_PERMISSION);
}
@@ -1626,12 +1629,13 @@
* Users of this method should instead invoke {@link #checkPermission}
* directly. This method will be changed in a future release
* to check the permission {@code java.security.AllPermission}.
+ * This method is subject to removal in a future version of Java SE.
*
* @see java.lang.reflect.Member
* @since 1.1
* @see #checkPermission(java.security.Permission) checkPermission
*/
- @Deprecated
+ @Deprecated(since="1.8", forRemoval=true)
@CallerSensitive
public void checkMemberAccess(Class<?> clazz, int which) {
if (clazz == null) {
--- a/jdk/src/java.base/share/classes/java/lang/Short.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/Short.java Thu Apr 21 13:37:31 2016 -0700
@@ -302,7 +302,13 @@
*
* @param value the value to be represented by the
* {@code Short}.
+ *
+ * @deprecated
+ * It is rarely appropriate to use this constructor. The static factory
+ * {@link #valueOf(short)} is generally a better choice, as it is
+ * likely to yield significantly better space and time performance.
*/
+ @Deprecated(since="9")
public Short(short value) {
this.value = value;
}
@@ -318,8 +324,14 @@
* {@code Short}
* @throws NumberFormatException If the {@code String}
* does not contain a parsable {@code short}.
- * @see java.lang.Short#parseShort(java.lang.String, int)
+ *
+ * @deprecated
+ * It is rarely appropriate to use this constructor.
+ * Use {@link #parseShort(String)} to convert a string to a
+ * {@code short} primitive, or use {@link #valueOf(String)}
+ * to convert a string to a {@code Short} object.
*/
+ @Deprecated(since="9")
public Short(String s) throws NumberFormatException {
this.value = parseShort(s, 10);
}
--- a/jdk/src/java.base/share/classes/java/lang/StackFrameInfo.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/StackFrameInfo.java Thu Apr 21 13:37:31 2016 -0700
@@ -37,24 +37,14 @@
private final static JavaLangInvokeAccess jlInvokeAccess =
SharedSecrets.getJavaLangInvokeAccess();
- // -XX:+MemberNameInStackFrame will initialize MemberName and all other fields;
- // otherwise, VM will set the hidden fields (injected by the VM).
- // -XX:+MemberNameInStackFrame is temporary to enable performance measurement
- //
- // Footprint improvement: MemberName::clazz and MemberName::name
- // can replace StackFrameInfo::declaringClass and StackFrameInfo::methodName
- // Currently VM sets StackFrameInfo::methodName instead of expanding MemberName::name
+ // Footprint improvement: MemberName::clazz can replace
+ // StackFrameInfo::declaringClass.
final StackWalker walker;
final Class<?> declaringClass;
final Object memberName;
- final int bci;
-
- // methodName, fileName, and lineNumber will be lazily set by the VM
- // when first requested.
- private String methodName;
- private String fileName = null; // default for unavailable filename
- private int lineNumber = -1; // default for unavailable lineNumber
+ final short bci;
+ private volatile StackTraceElement ste;
/*
* Create StackFrameInfo for StackFrameTraverser and LiveStackFrameTraverser
@@ -78,77 +68,53 @@
return declaringClass;
}
- // Call the VM to set methodName, lineNumber, and fileName
- private synchronized void ensureMethodInfoInitialized() {
- if (methodName == null) {
- setMethodInfo();
- }
- }
-
@Override
public String getMethodName() {
- ensureMethodInfoInitialized();
- return methodName;
+ return jlInvokeAccess.getName(memberName);
}
@Override
- public Optional<String> getFileName() {
- ensureMethodInfoInitialized();
- return fileName != null ? Optional.of(fileName) : Optional.empty();
+ public final Optional<String> getFileName() {
+ StackTraceElement ste = toStackTraceElement();
+ return ste.getFileName() != null ? Optional.of(ste.getFileName()) : Optional.empty();
}
@Override
- public OptionalInt getLineNumber() {
- ensureMethodInfoInitialized();
- return lineNumber > 0 ? OptionalInt.of(lineNumber) : OptionalInt.empty();
+ public final OptionalInt getLineNumber() {
+ StackTraceElement ste = toStackTraceElement();
+ return ste.getLineNumber() > 0 ? OptionalInt.of(ste.getLineNumber()) : OptionalInt.empty();
}
@Override
- public boolean isNativeMethod() {
- ensureMethodInfoInitialized();
- return lineNumber == -2;
+ public final boolean isNativeMethod() {
+ StackTraceElement ste = toStackTraceElement();
+ return ste.isNativeMethod();
}
@Override
public String toString() {
- ensureMethodInfoInitialized();
- // similar format as StackTraceElement::toString
- if (isNativeMethod()) {
- return getClassName() + "." + getMethodName() + "(Native Method)";
- } else {
- // avoid allocating Optional objects
- return getClassName() + "." + getMethodName() +
- "(" + (fileName != null ? fileName : "Unknown Source") +
- (lineNumber > 0 ? ":" + lineNumber : " bci:" + bci) + ")";
- }
+ StackTraceElement ste = toStackTraceElement();
+ return ste.toString();
}
/**
- * Lazily initialize method name, file name, line number
+ * Fill in the fields of the given StackTraceElement
*/
- private native void setMethodInfo();
-
- /**
- * Fill in source file name and line number of the given StackFrame array.
- */
- static native void fillInStackFrames(int startIndex,
- Object[] stackframes,
- int fromIndex, int toIndex);
+ private native void toStackTraceElement0(StackTraceElement ste);
@Override
public StackTraceElement toStackTraceElement() {
- ensureMethodInfoInitialized();
-
- Module module = declaringClass.getModule();
- String moduleName = module.isNamed() ? module.getName() : null;
- String moduleVersion = null;
- if (module.isNamed() && module.getDescriptor().version().isPresent()) {
- moduleVersion = module.getDescriptor().version().get().toString();
+ StackTraceElement s = ste;
+ if (s == null) {
+ synchronized (this) {
+ s = ste;
+ if (s == null) {
+ s = new StackTraceElement();
+ toStackTraceElement0(s);
+ ste = s;
+ }
+ }
}
- return new StackTraceElement(moduleName, moduleVersion,
- getClassName(), getMethodName(),
- fileName,
- lineNumber);
+ return s;
}
-
}
--- a/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java Thu Apr 21 13:37:31 2016 -0700
@@ -24,29 +24,22 @@
*/
package java.lang;
-import jdk.internal.misc.VM;
import jdk.internal.reflect.MethodAccessor;
-
-import java.io.PrintStream;
import java.lang.StackWalker.Option;
import java.lang.StackWalker.StackFrame;
import java.lang.annotation.Native;
import java.lang.reflect.Method;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.Arrays;
-import java.util.EnumSet;
import java.util.HashSet;
import java.util.NoSuchElementException;
import java.util.Objects;
-import java.util.Optional;
import java.util.Set;
import java.util.Spliterator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
+import sun.security.action.GetPropertyAction;
import static java.lang.StackStreamFactory.WalkerState.*;
@@ -61,8 +54,7 @@
* to avoid overhead of Stream/Lambda
* 1. Support traversing Stream<StackFrame>
* 2. StackWalker::getCallerClass
- * 3. Throwable::init and Throwable::getStackTrace
- * 4. AccessControlContext getting ProtectionDomain
+ * 3. AccessControlContext getting ProtectionDomain
*/
final class StackStreamFactory {
private StackStreamFactory() {}
@@ -79,25 +71,22 @@
// These flags must match the values maintained in the VM
@Native private static final int DEFAULT_MODE = 0x0;
@Native private static final int FILL_CLASS_REFS_ONLY = 0x2;
- @Native private static final int FILTER_FILL_IN_STACKTRACE = 0x10;
@Native private static final int SHOW_HIDDEN_FRAMES = 0x20; // LambdaForms are hidden by the VM
@Native private static final int FILL_LIVE_STACK_FRAMES = 0x100;
-
/*
* For Throwable to use StackWalker, set useNewThrowable to true.
* Performance work and extensive testing is needed to replace the
* VM built-in backtrace filled in Throwable with the StackWalker.
*/
- final static boolean useNewThrowable = getProperty("stackwalk.newThrowable", false);
final static boolean isDebug = getProperty("stackwalk.debug", false);
static <T> StackFrameTraverser<T>
makeStackTraverser(StackWalker walker, Function<? super Stream<StackFrame>, ? extends T> function)
{
if (walker.hasLocalsOperandsOption())
- return new LiveStackInfoTraverser<T>(walker, function);
+ return new LiveStackInfoTraverser<>(walker, function);
else
- return new StackFrameTraverser<T>(walker, function);
+ return new StackFrameTraverser<>(walker, function);
}
/**
@@ -107,40 +96,31 @@
return new CallerClassFinder(walker);
}
- static boolean useStackTrace(Throwable t) {
- if (t instanceof VirtualMachineError)
- return false;
-
- return VM.isBooted() && StackStreamFactory.useNewThrowable;
- }
-
- /*
- * This should only be used by Throwable::<init>.
- */
- static StackTrace makeStackTrace(Throwable ex) {
- return StackTrace.dump(ex);
- }
-
- /*
- * This creates StackTrace for Thread::dumpThread to use.
- */
- static StackTrace makeStackTrace() {
- return StackTrace.dump();
- }
-
enum WalkerState {
NEW, // the stream is new and stack walking has not started
OPEN, // the stream is open when it is being traversed.
CLOSED; // the stream is closed when the stack walking is done
}
- static abstract class AbstractStackWalker<T> {
+ /**
+ * Subclass of AbstractStackWalker implements a specific stack walking logic.
+ * It needs to set up the frame buffer and stack walking mode.
+ *
+ * It initiates the VM stack walking via the callStackWalk method that serves
+ * as the anchored frame and VM will call up to AbstractStackWalker::doStackWalk.
+ *
+ * @param <R> the type of the result returned from stack walking
+ * @param <T> the type of the data gathered for each frame.
+ * For example, StackFrameInfo for StackWalker::walk or
+ * Class<?> for StackWalker::getCallerClass
+ */
+ static abstract class AbstractStackWalker<R, T> {
protected final StackWalker walker;
protected final Thread thread;
protected final int maxDepth;
protected final long mode;
- protected int depth; // traversed stack depth
- protected FrameBuffer frameBuffer; // buffer for VM to fill in
+ protected int depth; // traversed stack depth
+ protected FrameBuffer<? extends T> frameBuffer;
protected long anchor;
// buffers to fill in stack frame information
@@ -158,16 +138,13 @@
private int toStackWalkMode(StackWalker walker, int mode) {
int newMode = mode;
if (walker.hasOption(Option.SHOW_HIDDEN_FRAMES) &&
- !fillCallerClassOnly(newMode) /* don't show hidden frames for getCallerClass */)
+ (mode & FILL_CLASS_REFS_ONLY) != FILL_CLASS_REFS_ONLY)
newMode |= SHOW_HIDDEN_FRAMES;
if (walker.hasLocalsOperandsOption())
newMode |= FILL_LIVE_STACK_FRAMES;
return newMode;
}
- private boolean fillCallerClassOnly(int mode) {
- return (mode|FILL_CLASS_REFS_ONLY) != FILL_CLASS_REFS_ONLY;
- }
/**
* A callback method to consume the stack frames. This method is invoked
* once stack walking begins (i.e. it is only invoked when walkFrames is called).
@@ -180,7 +157,7 @@
*
* @return the number of consumed frames
*/
- protected abstract T consumeFrames();
+ protected abstract R consumeFrames();
/**
* Initialize FrameBuffer. Subclass should implement this method to
@@ -253,7 +230,7 @@
* Walks stack frames until {@link #consumeFrames} is done consuming
* the frames it is interested in.
*/
- final T walk() {
+ final R walk() {
checkState(NEW);
try {
// VM will need to stablize the stack before walking. It will invoke
@@ -319,7 +296,7 @@
}
this.anchor = anchor; // set anchor for this bulk stack frame traversal
- frameBuffer.setBatch(bufStartIndex, bufEndIndex);
+ frameBuffer.setBatch(depth, bufStartIndex, bufEndIndex);
// traverse all frames and perform the action on the stack frames, if specified
return consumeFrames();
@@ -382,15 +359,14 @@
* If all fetched stack frames are traversed, AbstractStackWalker::fetchStackFrames will
* fetch the next batch of stack frames to continue.
*/
- private T beginStackWalk() {
+ private R beginStackWalk() {
// initialize buffers for VM to fill the stack frame info
initFrameBuffer();
return callStackWalk(mode, 0,
frameBuffer.curBatchFrameCount(),
frameBuffer.startIndex(),
- frameBuffer.classes,
- frameBuffer.stackFrames);
+ frameBuffer.frames());
}
/*
@@ -405,8 +381,7 @@
int endIndex = fetchStackFrames(mode, anchor, batchSize,
startIndex,
- frameBuffer.classes,
- frameBuffer.stackFrames);
+ frameBuffer.frames());
if (isDebug) {
System.out.format(" more stack walk requesting %d got %d to %d frames%n",
batchSize, frameBuffer.startIndex(), endIndex);
@@ -415,27 +390,26 @@
if (numFrames == 0) {
frameBuffer.freeze(); // done stack walking
} else {
- frameBuffer.setBatch(startIndex, endIndex);
+ frameBuffer.setBatch(depth, startIndex, endIndex);
}
return numFrames;
}
/**
* Begins stack walking. This method anchors this frame and invokes
- * AbstractStackWalker::doStackWalk after fetching the firt batch of stack frames.
+ * AbstractStackWalker::doStackWalk after fetching the first batch of stack frames.
*
* @param mode mode of stack walking
* @param skipframes number of frames to be skipped before filling the frame buffer.
* @param batchSize the batch size, max. number of elements to be filled in the frame buffers.
* @param startIndex start index of the frame buffers to be filled.
- * @param classes Classes buffer of the stack frames
- * @param frames StackFrame buffer, or null
+ * @param frames Either a Class<?> array, if mode is {@link #FILL_CLASS_REFS_ONLY}
+ * or a {@link StackFrameInfo} (or derivative) array otherwise.
* @return Result of AbstractStackWalker::doStackWalk
*/
- private native T callStackWalk(long mode, int skipframes,
+ private native R callStackWalk(long mode, int skipframes,
int batchSize, int startIndex,
- Class<?>[] classes,
- StackFrame[] frames);
+ T[] frames);
/**
* Fetch the next batch of stack frames.
@@ -444,185 +418,14 @@
* @param anchor
* @param batchSize the batch size, max. number of elements to be filled in the frame buffers.
* @param startIndex start index of the frame buffers to be filled.
- * @param classes Classes buffer of the stack frames
- * @param frames StackFrame buffer, or null
+ * @param frames Either a Class<?> array, if mode is {@link #FILL_CLASS_REFS_ONLY}
+ * or a {@link StackFrameInfo} (or derivative) array otherwise.
*
* @return the end index to the frame buffers
*/
private native int fetchStackFrames(long mode, long anchor,
int batchSize, int startIndex,
- Class<?>[] classes,
- StackFrame[] frames);
-
-
- /*
- * Frame buffer
- *
- * Each specialized AbstractStackWalker subclass may subclass the FrameBuffer.
- */
- class FrameBuffer {
- static final int START_POS = 2; // 0th and 1st elements are reserved
-
- // buffers for VM to fill stack frame info
- int currentBatchSize; // current batch size
- Class<?>[] classes; // caller class for fast path
-
- StackFrame[] stackFrames;
-
- int origin; // index to the current traversed stack frame
- int fence; // index to the last frame in the current batch
-
- FrameBuffer(int initialBatchSize) {
- if (initialBatchSize < MIN_BATCH_SIZE) {
- throw new IllegalArgumentException(initialBatchSize + " < minimum batch size: " + MIN_BATCH_SIZE);
- }
- this.origin = START_POS;
- this.fence = 0;
- this.currentBatchSize = initialBatchSize;
- this.classes = new Class<?>[currentBatchSize];
- }
-
- int curBatchFrameCount() {
- return currentBatchSize-START_POS;
- }
-
- /*
- * Tests if this frame buffer is empty. All frames are fetched.
- */
- final boolean isEmpty() {
- return origin >= fence || (origin == START_POS && fence == 0);
- }
-
- /*
- * Freezes this frame buffer. The stack stream source is done fetching.
- */
- final void freeze() {
- origin = 0;
- fence = 0;
- }
-
- /*
- * Tests if this frame buffer is active. It is inactive when
- * it is done for traversal. All stack frames have been traversed.
- */
- final boolean isActive() {
- return origin > 0 && (fence == 0 || origin < fence || fence == currentBatchSize);
- }
-
- /**
- * Gets the class at the current frame and move to the next frame.
- */
- final Class<?> next() {
- if (isEmpty()) {
- throw new NoSuchElementException("origin=" + origin + " fence=" + fence);
- }
- Class<?> c = classes[origin++];
- if (isDebug) {
- int index = origin-1;
- System.out.format(" next frame at %d: %s (origin %d fence %d)%n", index,
- Objects.toString(c), index, fence);
- }
- return c;
- }
-
- /**
- * Gets the class at the current frame.
- */
- final Class<?> get() {
- if (isEmpty()) {
- throw new NoSuchElementException("origin=" + origin + " fence=" + fence);
- }
- return classes[origin];
- }
-
- /*
- * Returns the index of the current frame.
- */
- final int getIndex() {
- return origin;
- }
-
- /*
- * Set the start and end index of a new batch of stack frames that have
- * been filled in this frame buffer.
- */
- final void setBatch(int startIndex, int endIndex) {
- if (startIndex <= 0 || endIndex <= 0)
- throw new IllegalArgumentException("startIndex=" + startIndex + " endIndex=" + endIndex);
-
- this.origin = startIndex;
- this.fence = endIndex;
- if (depth == 0 && fence > 0) {
- // filter the frames due to the stack stream implementation
- for (int i = START_POS; i < fence; i++) {
- Class<?> c = classes[i];
- if (isDebug) System.err.format(" frame %d: %s%n", i, c);
- if (filterStackWalkImpl(c)) {
- origin++;
- } else {
- break;
- }
- }
- }
- }
-
- /*
- * Checks if the origin is the expected start index.
- */
- final void check(int skipFrames) {
- int index = skipFrames + START_POS;
- if (origin != index) {
- // stack walk must continue with the previous frame depth
- throw new IllegalStateException("origin " + origin + " != " + index);
- }
- }
-
- // ------ subclass may override the following methods -------
- /**
- * Resizes the buffers for VM to fill in the next batch of stack frames.
- * The next batch will start at the given startIndex with the maximum number
- * of elements.
- *
- * <p> Subclass may override this method to manage the allocated buffers.
- *
- * @param startIndex the start index for the first frame of the next batch to fill in.
- * @param elements the number of elements for the next batch to fill in.
- *
- */
- void resize(int startIndex, int elements) {
- if (!isActive())
- throw new IllegalStateException("inactive frame buffer can't be resized");
-
- int size = startIndex+elements;
- if (classes.length < size) {
- // copy the elements in classes array to the newly allocated one.
- // classes[0] is a Thread object
- Class<?>[] prev = classes;
- classes = new Class<?>[size];
- System.arraycopy(prev, 0, classes, 0, START_POS);
- }
- currentBatchSize = size;
- }
-
- /*
- * Returns the start index for this frame buffer is refilled.
- *
- * This implementation reuses the allocated buffer for the next batch
- * of stack frames. For subclass to retain the fetched stack frames,
- * it should override this method to return the index at which the frame
- * should be filled in for the next batch.
- */
- int startIndex() {
- return START_POS;
- }
-
- /**
- * Returns next StackFrame object in the current batch of stack frames
- */
- StackFrame nextStackFrame() {
- throw new InternalError("should not reach here");
- }
- }
+ T[] frames);
}
/*
@@ -630,46 +433,66 @@
*
* This class implements Spliterator::forEachRemaining and Spliterator::tryAdvance.
*/
- static class StackFrameTraverser<T> extends AbstractStackWalker<T>
+ static class StackFrameTraverser<T> extends AbstractStackWalker<T, StackFrameInfo>
implements Spliterator<StackFrame>
{
static {
stackWalkImplClasses.add(StackFrameTraverser.class);
}
private static final int CHARACTERISTICS = Spliterator.ORDERED | Spliterator.IMMUTABLE;
- class Buffer extends FrameBuffer {
- Buffer(int initialBatchSize) {
+
+ final class StackFrameBuffer extends FrameBuffer<StackFrameInfo> {
+ private StackFrameInfo[] stackFrames;
+ StackFrameBuffer(int initialBatchSize) {
super(initialBatchSize);
- this.stackFrames = new StackFrame[initialBatchSize];
+ this.stackFrames = new StackFrameInfo[initialBatchSize];
for (int i = START_POS; i < initialBatchSize; i++) {
stackFrames[i] = new StackFrameInfo(walker);
}
}
@Override
+ StackFrameInfo[] frames() {
+ return stackFrames;
+ }
+
+ @Override
void resize(int startIndex, int elements) {
- super.resize(startIndex, elements);
+ if (!isActive())
+ throw new IllegalStateException("inactive frame buffer can't be resized");
+
+ assert startIndex == START_POS :
+ "bad start index " + startIndex + " expected " + START_POS;
int size = startIndex+elements;
if (stackFrames.length < size) {
- stackFrames = new StackFrame[size];
+ StackFrameInfo[] newFrames = new StackFrameInfo[size];
+ // copy initial magic...
+ System.arraycopy(stackFrames, 0, newFrames, 0, startIndex);
+ stackFrames = newFrames;
}
- for (int i = startIndex(); i < size; i++) {
+ for (int i = startIndex; i < size; i++) {
stackFrames[i] = new StackFrameInfo(walker);
}
+ currentBatchSize = size;
}
@Override
- StackFrame nextStackFrame() {
+ StackFrameInfo nextStackFrame() {
if (isEmpty()) {
throw new NoSuchElementException("origin=" + origin + " fence=" + fence);
}
- StackFrame frame = stackFrames[origin];
+ StackFrameInfo frame = stackFrames[origin];
origin++;
return frame;
}
+
+ @Override
+ final Class<?> at(int index) {
+ return stackFrames[index].declaringClass;
+ }
}
final Function<? super Stream<StackFrame>, ? extends T> function; // callback
@@ -694,7 +517,7 @@
return null;
}
- StackFrame frame = frameBuffer.nextStackFrame();
+ StackFrameInfo frame = frameBuffer.nextStackFrame();
depth++;
return frame;
}
@@ -711,7 +534,7 @@
@Override
protected void initFrameBuffer() {
- this.frameBuffer = new Buffer(getNextBatchSize());
+ this.frameBuffer = new StackFrameBuffer(getNextBatchSize());
}
@Override
@@ -782,7 +605,7 @@
* CallerClassFinder is specialized to return Class<?> for each stack frame.
* StackFrame is not requested.
*/
- static class CallerClassFinder extends AbstractStackWalker<Integer> {
+ static final class CallerClassFinder extends AbstractStackWalker<Integer, Class<?>> {
static {
stackWalkImplClasses.add(CallerClassFinder.class);
}
@@ -791,6 +614,54 @@
CallerClassFinder(StackWalker walker) {
super(walker, FILL_CLASS_REFS_ONLY);
+ assert (mode & FILL_CLASS_REFS_ONLY) == FILL_CLASS_REFS_ONLY
+ : "mode should contain FILL_CLASS_REFS_ONLY";
+ }
+
+ final class ClassBuffer extends FrameBuffer<Class<?>> {
+ Class<?>[] classes; // caller class for fast path
+ ClassBuffer(int batchSize) {
+ super(batchSize);
+ classes = new Class<?>[batchSize];
+ }
+
+ @Override
+ Class<?>[] frames() { return classes;}
+
+ @Override
+ final Class<?> at(int index) { return classes[index];}
+
+
+ // ------ subclass may override the following methods -------
+ /**
+ * Resizes the buffers for VM to fill in the next batch of stack frames.
+ * The next batch will start at the given startIndex with the maximum number
+ * of elements.
+ *
+ * <p> Subclass may override this method to manage the allocated buffers.
+ *
+ * @param startIndex the start index for the first frame of the next batch to fill in.
+ * @param elements the number of elements for the next batch to fill in.
+ *
+ */
+ @Override
+ void resize(int startIndex, int elements) {
+ if (!isActive())
+ throw new IllegalStateException("inactive frame buffer can't be resized");
+
+ assert startIndex == START_POS :
+ "bad start index " + startIndex + " expected " + START_POS;
+
+ int size = startIndex+elements;
+ if (classes.length < size) {
+ // copy the elements in classes array to the newly allocated one.
+ // classes[0] is a Thread object
+ Class<?>[] prev = classes;
+ classes = new Class<?>[size];
+ System.arraycopy(prev, 0, classes, 0, startIndex);
+ }
+ currentBatchSize = size;
+ }
}
Class<?> findCaller() {
@@ -811,15 +682,15 @@
if (isMethodHandleFrame(caller)) continue;
frames[n++] = caller;
}
-
- if (frames[1] == null)
+ if (frames[1] == null) {
throw new IllegalStateException("no caller frame");
+ }
return n;
}
@Override
protected void initFrameBuffer() {
- this.frameBuffer = new FrameBuffer(getNextBatchSize());
+ this.frameBuffer = new ClassBuffer(getNextBatchSize());
}
@Override
@@ -833,215 +704,64 @@
}
}
- /*
- * StackTrace caches all frames in the buffer. StackTraceElements are
- * created lazily when Throwable::getStackTrace is called.
- */
- static class StackTrace extends AbstractStackWalker<Integer> {
- static {
- stackWalkImplClasses.add(StackTrace.class);
- }
-
- class GrowableBuffer extends FrameBuffer {
- GrowableBuffer(int initialBatchSize) {
- super(initialBatchSize);
-
- this.stackFrames = new StackFrame[initialBatchSize];
- for (int i = START_POS; i < initialBatchSize; i++) {
- stackFrames[i] = new StackFrameInfo(walker);
- }
- }
-
- /*
- * Returns the next index to fill
- */
- @Override
- int startIndex() {
- return origin;
- }
-
- /**
- * Initialize the buffers for VM to fill in the stack frame information.
- * The next batch will start at the given startIndex to
- * the length of the buffer.
- */
- @Override
- void resize(int startIndex, int elements) {
- // Expand the frame buffer.
- // Do not call super.resize that will reuse the filled elements
- // in this frame buffer
- int size = startIndex+elements;
- if (classes.length < size) {
- // resize the frame buffer
- classes = Arrays.copyOf(classes, size);
- stackFrames = Arrays.copyOf(stackFrames, size);
- }
- for (int i = startIndex; i < size; i++) {
- stackFrames[i] = new StackFrameInfo(walker);
- }
- currentBatchSize = size;
- }
-
- StackTraceElement get(int index) {
- return new StackTraceElement(classes[index].getName(), "unknown", null, -1);
- }
-
- /**
- * Returns an array of StackTraceElement for all stack frames cached in
- * this StackTrace object.
- * <p>
- * This method is intended for Throwable::getOurStackTrace use only.
- */
- StackTraceElement[] toStackTraceElements() {
- int startIndex = START_POS;
- for (int i = startIndex; i < classes.length; i++) {
- if (classes[i] != null && filterStackWalkImpl(classes[i])) {
- startIndex++;
- } else {
- break;
- }
- }
-
- // VM fills in the method name, filename, line number info
- StackFrameInfo.fillInStackFrames(0, stackFrames, startIndex, startIndex + depth);
-
- StackTraceElement[] stes = new StackTraceElement[depth];
- for (int i = startIndex, j = 0; i < classes.length && j < depth; i++, j++) {
- if (isDebug) {
- System.err.println("StackFrame: " + i + " " + stackFrames[i]);
- }
- stes[j] = stackFrames[i].toStackTraceElement();
- }
- return stes;
- }
- }
-
- private static final int MAX_STACK_FRAMES = 1024;
- private static final StackWalker STACKTRACE_WALKER =
- StackWalker.newInstanceNoCheck(EnumSet.of(Option.SHOW_REFLECT_FRAMES));
-
- private StackTraceElement[] stes;
- static StackTrace dump() {
- return new StackTrace();
- }
-
- static StackTrace dump(Throwable ex) {
- return new StackTrace(ex);
- }
-
- private StackTrace() {
- this(STACKTRACE_WALKER, DEFAULT_MODE);
- }
-
- /*
- * Throwable::fillInStackTrace and <init> of Throwable and subclasses
- * are filtered in the VM.
- */
- private StackTrace(Throwable ex) {
- this(STACKTRACE_WALKER, FILTER_FILL_IN_STACKTRACE); // skip Throwable::init frames
- if (isDebug) {
- System.err.println("dump stack for " + ex.getClass().getName());
- }
- }
-
- StackTrace(StackWalker walker, int mode) {
- super(walker, mode, MAX_STACK_FRAMES);
-
- // snapshot the stack trace
- walk();
- }
-
- @Override
- protected Integer consumeFrames() {
- // traverse all frames and perform the action on the stack frames, if specified
- int n = 0;
- while (n < maxDepth && nextFrame() != null) {
- n++;
- }
- return n;
- }
-
- @Override
- protected void initFrameBuffer() {
- this.frameBuffer = new GrowableBuffer(getNextBatchSize());
- }
-
- // TODO: implement better heuristic
- @Override
- protected int batchSize(int lastBatchFrameCount) {
- // chunk size of VM backtrace is 32
- return lastBatchFrameCount == 0 ? 32 : 32;
- }
-
- /**
- * Returns an array of StackTraceElement for all stack frames cached in
- * this StackTrace object.
- * <p>
- * This method is intended for Throwable::getOurStackTrace use only.
- */
- synchronized StackTraceElement[] getStackTraceElements() {
- if (stes == null) {
- stes = ((GrowableBuffer) frameBuffer).toStackTraceElements();
- // release the frameBuffer memory
- frameBuffer = null;
- }
- return stes;
- }
-
- /*
- * Prints stack trace to the given PrintStream.
- *
- * Further implementation could skip creating StackTraceElement objects
- * print directly to the PrintStream.
- */
- void printStackTrace(PrintStream s) {
- StackTraceElement[] stes = getStackTraceElements();
- synchronized (s) {
- s.println("Stack trace");
- for (StackTraceElement traceElement : stes)
- s.println("\tat " + traceElement);
- }
- }
- }
-
- static class LiveStackInfoTraverser<T> extends StackFrameTraverser<T> {
+ static final class LiveStackInfoTraverser<T> extends StackFrameTraverser<T> {
static {
stackWalkImplClasses.add(LiveStackInfoTraverser.class);
}
// VM will fill in all method info and live stack info directly in StackFrameInfo
- class Buffer extends FrameBuffer {
- Buffer(int initialBatchSize) {
+ final class LiveStackFrameBuffer extends FrameBuffer<LiveStackFrameInfo> {
+ private LiveStackFrameInfo[] stackFrames;
+ LiveStackFrameBuffer(int initialBatchSize) {
super(initialBatchSize);
- this.stackFrames = new StackFrame[initialBatchSize];
+ this.stackFrames = new LiveStackFrameInfo[initialBatchSize];
for (int i = START_POS; i < initialBatchSize; i++) {
stackFrames[i] = new LiveStackFrameInfo(walker);
}
}
@Override
+ LiveStackFrameInfo[] frames() {
+ return stackFrames;
+ }
+
+ @Override
void resize(int startIndex, int elements) {
- super.resize(startIndex, elements);
+ if (!isActive()) {
+ throw new IllegalStateException("inactive frame buffer can't be resized");
+ }
+ assert startIndex == START_POS :
+ "bad start index " + startIndex + " expected " + START_POS;
+
int size = startIndex + elements;
-
if (stackFrames.length < size) {
- this.stackFrames = new StackFrame[size];
+ LiveStackFrameInfo[] newFrames = new LiveStackFrameInfo[size];
+ // copy initial magic...
+ System.arraycopy(stackFrames, 0, newFrames, 0, startIndex);
+ stackFrames = newFrames;
}
for (int i = startIndex(); i < size; i++) {
stackFrames[i] = new LiveStackFrameInfo(walker);
}
+
+ currentBatchSize = size;
}
@Override
- StackFrame nextStackFrame() {
+ LiveStackFrameInfo nextStackFrame() {
if (isEmpty()) {
throw new NoSuchElementException("origin=" + origin + " fence=" + fence);
}
- StackFrame frame = stackFrames[origin];
+ LiveStackFrameInfo frame = stackFrames[origin];
origin++;
return frame;
}
+
+ @Override
+ final Class<?> at(int index) {
+ return stackFrames[index].declaringClass;
+ }
}
LiveStackInfoTraverser(StackWalker walker,
@@ -1051,7 +771,183 @@
@Override
protected void initFrameBuffer() {
- this.frameBuffer = new Buffer(getNextBatchSize());
+ this.frameBuffer = new LiveStackFrameBuffer(getNextBatchSize());
+ }
+ }
+
+ /*
+ * Frame buffer
+ *
+ * Each specialized AbstractStackWalker subclass may subclass the FrameBuffer.
+ */
+ static abstract class FrameBuffer<F> {
+ static final int START_POS = 2; // 0th and 1st elements are reserved
+
+ // buffers for VM to fill stack frame info
+ int currentBatchSize; // current batch size
+ int origin; // index to the current traversed stack frame
+ int fence; // index to the last frame in the current batch
+
+ FrameBuffer(int initialBatchSize) {
+ if (initialBatchSize < MIN_BATCH_SIZE) {
+ throw new IllegalArgumentException(initialBatchSize +
+ " < minimum batch size: " + MIN_BATCH_SIZE);
+ }
+ this.origin = START_POS;
+ this.fence = 0;
+ this.currentBatchSize = initialBatchSize;
+ }
+
+ /**
+ * Returns an array of frames that may be used to store frame objects
+ * when walking the stack.
+ *
+ * May be an array of {@code Class<?>} if the {@code AbstractStackWalker}
+ * mode is {@link #FILL_CLASS_REFS_ONLY}, or an array of
+ * {@link StackFrameInfo} (or derivative) array otherwise.
+ *
+ * @return An array of frames that may be used to store frame objects
+ * when walking the stack. Must not be null.
+ */
+ abstract F[] frames(); // must not return null
+
+ /**
+ * Resizes the buffers for VM to fill in the next batch of stack frames.
+ * The next batch will start at the given startIndex with the maximum number
+ * of elements.
+ *
+ * <p> Subclass may override this method to manage the allocated buffers.
+ *
+ * @param startIndex the start index for the first frame of the next batch to fill in.
+ * @param elements the number of elements for the next batch to fill in.
+ *
+ */
+ abstract void resize(int startIndex, int elements);
+
+ /**
+ * Return the class at the given position in the current batch.
+ * @param index the position of the frame.
+ * @return the class at the given position in the current batch.
+ */
+ abstract Class<?> at(int index);
+
+ // ------ subclass may override the following methods -------
+
+ /*
+ * Returns the start index for this frame buffer is refilled.
+ *
+ * This implementation reuses the allocated buffer for the next batch
+ * of stack frames. For subclass to retain the fetched stack frames,
+ * it should override this method to return the index at which the frame
+ * should be filled in for the next batch.
+ */
+ int startIndex() {
+ return START_POS;
+ }
+
+ /**
+ * Returns next StackFrame object in the current batch of stack frames
+ */
+ F nextStackFrame() {
+ throw new InternalError("should not reach here");
+ }
+
+ // ------ FrameBuffer implementation ------
+
+ final int curBatchFrameCount() {
+ return currentBatchSize-START_POS;
+ }
+
+ /*
+ * Tests if this frame buffer is empty. All frames are fetched.
+ */
+ final boolean isEmpty() {
+ return origin >= fence || (origin == START_POS && fence == 0);
+ }
+
+ /*
+ * Freezes this frame buffer. The stack stream source is done fetching.
+ */
+ final void freeze() {
+ origin = 0;
+ fence = 0;
+ }
+
+ /*
+ * Tests if this frame buffer is active. It is inactive when
+ * it is done for traversal. All stack frames have been traversed.
+ */
+ final boolean isActive() {
+ return origin > 0 && (fence == 0 || origin < fence || fence == currentBatchSize);
+ }
+
+ /**
+ * Gets the class at the current frame and move to the next frame.
+ */
+ final Class<?> next() {
+ if (isEmpty()) {
+ throw new NoSuchElementException("origin=" + origin + " fence=" + fence);
+ }
+ Class<?> c = at(origin);
+ origin++;
+ if (isDebug) {
+ int index = origin-1;
+ System.out.format(" next frame at %d: %s (origin %d fence %d)%n", index,
+ Objects.toString(c), index, fence);
+ }
+ return c;
+ }
+
+ /**
+ * Gets the class at the current frame.
+ */
+ final Class<?> get() {
+ if (isEmpty()) {
+ throw new NoSuchElementException("origin=" + origin + " fence=" + fence);
+ }
+ return at(origin);
+ }
+
+ /*
+ * Returns the index of the current frame.
+ */
+ final int getIndex() {
+ return origin;
+ }
+
+ /*
+ * Set the start and end index of a new batch of stack frames that have
+ * been filled in this frame buffer.
+ */
+ final void setBatch(int depth, int startIndex, int endIndex) {
+ if (startIndex <= 0 || endIndex <= 0)
+ throw new IllegalArgumentException("startIndex=" + startIndex + " endIndex=" + endIndex);
+
+ this.origin = startIndex;
+ this.fence = endIndex;
+ if (depth == 0 && fence > 0) {
+ // filter the frames due to the stack stream implementation
+ for (int i = START_POS; i < fence; i++) {
+ Class<?> c = at(i);
+ if (isDebug) System.err.format(" frame %d: %s%n", i, c);
+ if (filterStackWalkImpl(c)) {
+ origin++;
+ } else {
+ break;
+ }
+ }
+ }
+ }
+
+ /*
+ * Checks if the origin is the expected start index.
+ */
+ final void check(int skipFrames) {
+ int index = skipFrames + START_POS;
+ if (origin != index) {
+ // stack walk must continue with the previous frame depth
+ throw new IllegalStateException("origin " + origin + " != " + index);
+ }
}
}
@@ -1093,14 +989,9 @@
}
private static boolean getProperty(String key, boolean value) {
- String s = AccessController.doPrivileged(new PrivilegedAction<>() {
- @Override
- public String run() {
- return System.getProperty(key);
- }
- });
+ String s = GetPropertyAction.getProperty(key);
if (s != null) {
- return Boolean.valueOf(s);
+ return Boolean.parseBoolean(s);
}
return value;
}
--- a/jdk/src/java.base/share/classes/java/lang/String.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/String.java Thu Apr 21 13:37:31 2016 -0700
@@ -363,7 +363,7 @@
* @see #String(byte[], java.nio.charset.Charset)
* @see #String(byte[])
*/
- @Deprecated
+ @Deprecated(since="1.1")
public String(byte ascii[], int hibyte, int offset, int count) {
checkBoundsOffCount(offset, count, ascii.length);
if (count == 0) {
@@ -415,7 +415,7 @@
* @see #String(byte[], java.nio.charset.Charset)
* @see #String(byte[])
*/
- @Deprecated
+ @Deprecated(since="1.1")
public String(byte ascii[], int hibyte) {
this(ascii, hibyte, 0, ascii.length);
}
@@ -911,7 +911,7 @@
* dst.length}
* </ul>
*/
- @Deprecated
+ @Deprecated(since="1.1")
public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin) {
checkBoundsBeginEnd(srcBegin, srcEnd, length());
Objects.requireNonNull(dst);
--- a/jdk/src/java.base/share/classes/java/lang/System.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/System.java Thu Apr 21 13:37:31 2016 -0700
@@ -1715,6 +1715,7 @@
* finalizers being called on live objects while other threads are
* concurrently manipulating those objects, resulting in erratic
* behavior or deadlock.
+ * This method is subject to removal in a future version of Java SE.
* @param value indicating enabling or disabling of finalization
* @throws SecurityException
* if a security manager exists and its <code>checkExit</code>
@@ -1725,7 +1726,7 @@
* @see java.lang.SecurityManager#checkExit(int)
* @since 1.1
*/
- @Deprecated
+ @Deprecated(since="1.2", forRemoval=true)
public static void runFinalizersOnExit(boolean value) {
Runtime.runFinalizersOnExit(value);
}
--- a/jdk/src/java.base/share/classes/java/lang/Thread.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/Thread.java Thu Apr 21 13:37:31 2016 -0700
@@ -890,7 +890,7 @@
* <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
* are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
*/
- @Deprecated
+ @Deprecated(since="1.2")
public final void stop() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
@@ -922,8 +922,9 @@
* For more information, see
* <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
* are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
+ * This method is subject to removal in a future version of Java SE.
*/
- @Deprecated
+ @Deprecated(since="1.2", forRemoval=true)
public final synchronized void stop(Throwable obj) {
throw new UnsupportedOperationException();
}
@@ -1043,9 +1044,10 @@
* "frozen" processes. For more information, see
* <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">
* Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
+ * This method is subject to removal in a future version of Java SE.
* @throws NoSuchMethodError always
*/
- @Deprecated
+ @Deprecated(since="1.5", forRemoval=true)
public void destroy() {
throw new NoSuchMethodError();
}
@@ -1083,7 +1085,7 @@
* <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
* are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
*/
- @Deprecated
+ @Deprecated(since="1.2")
public final void suspend() {
checkAccess();
suspend0();
@@ -1109,7 +1111,7 @@
* <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
* are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
*/
- @Deprecated
+ @Deprecated(since="1.2")
public final void resume() {
checkAccess();
resume0();
@@ -1270,8 +1272,10 @@
* @deprecated The definition of this call depends on {@link #suspend},
* which is deprecated. Further, the results of this call
* were never well-defined.
+ * This method is subject to removal in a future version of Java SE.
+ * @see StackWalker
*/
- @Deprecated
+ @Deprecated(since="1.2", forRemoval=true)
public native int countStackFrames();
/**
@@ -1388,7 +1392,7 @@
* This method is used only for debugging.
*/
public static void dumpStack() {
- StackStreamFactory.makeStackTrace().printStackTrace(System.err);
+ new Exception("Stack trace").printStackTrace();
}
/**
@@ -1610,8 +1614,7 @@
}
return stackTrace;
} else {
- // Don't need JVM help for current thread
- return StackStreamFactory.makeStackTrace().getStackTraceElements();
+ return (new Exception()).getStackTrace();
}
}
--- a/jdk/src/java.base/share/classes/java/lang/ThreadGroup.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/ThreadGroup.java Thu Apr 21 13:37:31 2016 -0700
@@ -607,7 +607,7 @@
* @deprecated This method is inherently unsafe. See
* {@link Thread#stop} for details.
*/
- @Deprecated
+ @Deprecated(since="1.2")
public final void stop() {
if (stopOrSuspend(false))
Thread.currentThread().stop();
@@ -669,7 +669,7 @@
* @deprecated This method is inherently deadlock-prone. See
* {@link Thread#suspend} for details.
*/
- @Deprecated
+ @Deprecated(since="1.2")
@SuppressWarnings("deprecation")
public final void suspend() {
if (stopOrSuspend(true))
@@ -732,7 +732,7 @@
* both of which have been deprecated, as they are inherently
* deadlock-prone. See {@link Thread#suspend} for details.
*/
- @Deprecated
+ @Deprecated(since="1.2")
@SuppressWarnings("deprecation")
public final void resume() {
int ngroupsSnapshot;
@@ -1073,7 +1073,7 @@
* which is deprecated. Further, the behavior of this call
* was never specified.
*/
- @Deprecated
+ @Deprecated(since="1.2")
public boolean allowThreadSuspension(boolean b) {
this.vmAllowSuspension = b;
if (!b) {
--- a/jdk/src/java.base/share/classes/java/lang/Throwable.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/Throwable.java Thu Apr 21 13:37:31 2016 -0700
@@ -785,11 +785,7 @@
public synchronized Throwable fillInStackTrace() {
if (stackTrace != null ||
backtrace != null /* Out of protocol state */ ) {
- if (backtrace == null && StackStreamFactory.useStackTrace(this)) {
- backtrace = StackStreamFactory.makeStackTrace(this);
- } else {
- fillInStackTrace(0);
- }
+ fillInStackTrace(0);
stackTrace = UNASSIGNED_STACK;
}
return this;
@@ -830,15 +826,11 @@
// backtrace if this is the first call to this method
if (stackTrace == UNASSIGNED_STACK ||
(stackTrace == null && backtrace != null) /* Out of protocol state */) {
- if (backtrace instanceof StackStreamFactory.StackTrace) {
- stackTrace = ((StackStreamFactory.StackTrace)backtrace).getStackTraceElements();
- } else {
- stackTrace = new StackTraceElement[depth];
- for (int i = 0; i < depth; i++) {
- stackTrace[i] = new StackTraceElement();
- }
- getStackTraceElements(stackTrace);
+ stackTrace = new StackTraceElement[depth];
+ for (int i = 0; i < depth; i++) {
+ stackTrace[i] = new StackTraceElement();
}
+ getStackTraceElements(stackTrace);
} else if (stackTrace == null) {
return UNASSIGNED_STACK;
}
--- a/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java Thu Apr 21 13:37:31 2016 -0700
@@ -88,8 +88,7 @@
static {
final String key = "jdk.internal.lambda.dumpProxyClasses";
- String path = AccessController.doPrivileged(
- new GetPropertyAction(key));
+ String path = GetPropertyAction.getProperty(key);
dumper = (null == path) ? null : ProxyClassesDumper.getInstance(path);
}
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java Thu Apr 21 13:37:31 2016 -0700
@@ -733,6 +733,7 @@
}
@Override
+ @SuppressWarnings("deprecation")
public int hashCode() {
// Avoid autoboxing getReferenceKind(), since this is used early and will force
// early initialization of Byte$ByteCache
@@ -826,7 +827,7 @@
assert(isResolved() == isResolved);
}
- void checkForTypeAlias() {
+ void checkForTypeAlias(Class<?> refc) {
if (isInvocable()) {
MethodType type;
if (this.type instanceof MethodType)
@@ -834,16 +835,16 @@
else
this.type = type = getMethodType();
if (type.erase() == type) return;
- if (VerifyAccess.isTypeVisible(type, clazz)) return;
- throw new LinkageError("bad method type alias: "+type+" not visible from "+clazz);
+ if (VerifyAccess.isTypeVisible(type, refc)) return;
+ throw new LinkageError("bad method type alias: "+type+" not visible from "+refc);
} else {
Class<?> type;
if (this.type instanceof Class<?>)
type = (Class<?>) this.type;
else
this.type = type = getFieldType();
- if (VerifyAccess.isTypeVisible(type, clazz)) return;
- throw new LinkageError("bad field type alias: "+type+" not visible from "+clazz);
+ if (VerifyAccess.isTypeVisible(type, refc)) return;
+ throw new LinkageError("bad field type alias: "+type+" not visible from "+refc);
}
}
@@ -1015,10 +1016,25 @@
MemberName m = ref.clone(); // JVM will side-effect the ref
assert(refKind == m.getReferenceKind());
try {
+ // There are 4 entities in play here:
+ // * LC: lookupClass
+ // * REFC: symbolic reference class (MN.clazz before resolution);
+ // * DEFC: resolved method holder (MN.clazz after resolution);
+ // * PTYPES: parameter types (MN.type)
+ //
+ // What we care about when resolving a MemberName is consistency between DEFC and PTYPES.
+ // We do type alias (TA) checks on DEFC to ensure that. DEFC is not known until the JVM
+ // finishes the resolution, so do TA checks right after MHN.resolve() is over.
+ //
+ // All parameters passed by a caller are checked against MH type (PTYPES) on every invocation,
+ // so it is safe to call a MH from any context.
+ //
+ // REFC view on PTYPES doesn't matter, since it is used only as a starting point for resolution and doesn't
+ // participate in method selection.
m = MethodHandleNatives.resolve(m, lookupClass);
- m.checkForTypeAlias();
+ m.checkForTypeAlias(m.getDeclaringClass());
m.resolution = null;
- } catch (LinkageError ex) {
+ } catch (ClassNotFoundException | LinkageError ex) {
// JVM reports that the "bytecode behavior" would get an error
assert(!m.isResolved());
m.resolution = ex;
@@ -1132,6 +1148,10 @@
public Object newMemberName() {
return new MemberName();
}
+ public String getName(Object mname) {
+ MemberName memberName = (MemberName)mname;
+ return memberName.getName();
+ }
});
}
}
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java Thu Apr 21 13:37:31 2016 -0700
@@ -49,7 +49,7 @@
static native void init(MemberName self, Object ref);
static native void expand(MemberName self);
- static native MemberName resolve(MemberName self, Class<?> caller) throws LinkageError;
+ static native MemberName resolve(MemberName self, Class<?> caller) throws LinkageError, ClassNotFoundException;
static native int getMembers(Class<?> defc, String matchName, String matchSig,
int matchFlags, Class<?> caller, int skip, MemberName[] results);
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java Thu Apr 21 13:37:31 2016 -0700
@@ -25,9 +25,9 @@
package java.lang.invoke;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
+import java.util.Properties;
import jdk.internal.misc.Unsafe;
+import sun.security.action.GetPropertyAction;
/**
* This class consists exclusively of static names internal to the
@@ -53,32 +53,27 @@
static final boolean VAR_HANDLE_GUARDS;
static {
- final Object[] values = new Object[10];
- AccessController.doPrivileged(new PrivilegedAction<>() {
- public Void run() {
- values[0] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES");
- values[1] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DUMP_CLASS_FILES");
- values[2] = Boolean.getBoolean("java.lang.invoke.MethodHandle.TRACE_INTERPRETER");
- values[3] = Boolean.getBoolean("java.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE");
- values[4] = Integer.getInteger("java.lang.invoke.MethodHandle.COMPILE_THRESHOLD", 0);
- values[5] = Integer.getInteger("java.lang.invoke.MethodHandle.DONT_INLINE_THRESHOLD", 30);
- values[6] = Integer.getInteger("java.lang.invoke.MethodHandle.PROFILE_LEVEL", 0);
- values[7] = Boolean.parseBoolean(System.getProperty("java.lang.invoke.MethodHandle.PROFILE_GWT", "true"));
- values[8] = Integer.getInteger("java.lang.invoke.MethodHandle.CUSTOMIZE_THRESHOLD", 127);
- values[9] = Boolean.parseBoolean(System.getProperty("java.lang.invoke.VarHandle.VAR_HANDLE_GUARDS", "true"));
- return null;
- }
- });
- DEBUG_METHOD_HANDLE_NAMES = (Boolean) values[0];
- DUMP_CLASS_FILES = (Boolean) values[1];
- TRACE_INTERPRETER = (Boolean) values[2];
- TRACE_METHOD_LINKAGE = (Boolean) values[3];
- COMPILE_THRESHOLD = (Integer) values[4];
- DONT_INLINE_THRESHOLD = (Integer) values[5];
- PROFILE_LEVEL = (Integer) values[6];
- PROFILE_GWT = (Boolean) values[7];
- CUSTOMIZE_THRESHOLD = (Integer) values[8];
- VAR_HANDLE_GUARDS = (Boolean) values[9];
+ Properties props = GetPropertyAction.getProperties();
+ DEBUG_METHOD_HANDLE_NAMES = Boolean.parseBoolean(
+ props.getProperty("java.lang.invoke.MethodHandle.DEBUG_NAMES"));
+ DUMP_CLASS_FILES = Boolean.parseBoolean(
+ props.getProperty("java.lang.invoke.MethodHandle.DUMP_CLASS_FILES"));
+ TRACE_INTERPRETER = Boolean.parseBoolean(
+ props.getProperty("java.lang.invoke.MethodHandle.TRACE_INTERPRETER"));
+ TRACE_METHOD_LINKAGE = Boolean.parseBoolean(
+ props.getProperty("java.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE"));
+ COMPILE_THRESHOLD = Integer.parseInt(
+ props.getProperty("java.lang.invoke.MethodHandle.COMPILE_THRESHOLD", "0"));
+ DONT_INLINE_THRESHOLD = Integer.parseInt(
+ props.getProperty("java.lang.invoke.MethodHandle.DONT_INLINE_THRESHOLD", "30"));
+ PROFILE_LEVEL = Integer.parseInt(
+ props.getProperty("java.lang.invoke.MethodHandle.PROFILE_LEVEL", "0"));
+ PROFILE_GWT = Boolean.parseBoolean(
+ props.getProperty("java.lang.invoke.MethodHandle.PROFILE_GWT", "true"));
+ CUSTOMIZE_THRESHOLD = Integer.parseInt(
+ props.getProperty("java.lang.invoke.MethodHandle.CUSTOMIZE_THRESHOLD", "127"));
+ VAR_HANDLE_GUARDS = Boolean.parseBoolean(
+ props.getProperty("java.lang.invoke.VarHandle.VAR_HANDLE_GUARDS", "true"));
if (CUSTOMIZE_THRESHOLD < -1 || CUSTOMIZE_THRESHOLD > 127) {
throw newInternalError("CUSTOMIZE_THRESHOLD should be in [-1...127] range");
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Thu Apr 21 13:37:31 2016 -0700
@@ -28,6 +28,7 @@
import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.BitSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Arrays;
import java.util.Objects;
@@ -53,6 +54,7 @@
import jdk.internal.org.objectweb.asm.Opcodes;
import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
+import static java.lang.invoke.MethodType.methodType;
/**
* This class consists exclusively of static methods that operate on or return
@@ -3000,7 +3002,7 @@
private static final MethodHandle[] IDENTITY_MHS = new MethodHandle[Wrapper.values().length];
private static MethodHandle makeIdentity(Class<?> ptype) {
- MethodType mtype = MethodType.methodType(ptype, ptype);
+ MethodType mtype = methodType(ptype, ptype);
LambdaForm lform = LambdaForm.identityForm(BasicType.basicType(ptype));
return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.IDENTITY);
}
@@ -3018,7 +3020,7 @@
}
private static final MethodHandle[] ZERO_MHS = new MethodHandle[Wrapper.values().length];
private static MethodHandle makeZero(Class<?> rtype) {
- MethodType mtype = MethodType.methodType(rtype);
+ MethodType mtype = methodType(rtype);
LambdaForm lform = LambdaForm.zeroForm(BasicType.basicType(rtype));
return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.ZERO);
}
@@ -3929,7 +3931,7 @@
MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType) {
if (!Throwable.class.isAssignableFrom(exType))
throw new ClassCastException(exType.getName());
- return MethodHandleImpl.throwException(MethodType.methodType(returnType, exType));
+ return MethodHandleImpl.throwException(methodType(returnType, exType));
}
/**
@@ -4166,7 +4168,7 @@
for (int i = 0; i < nclauses; ++i) {
Class<?> t = iterationVariableTypes.get(i);
if (init.get(i) == null) {
- init.set(i, empty(MethodType.methodType(t, commonSuffix)));
+ init.set(i, empty(methodType(t, commonSuffix)));
}
if (step.get(i) == null) {
step.set(i, dropArgumentsToMatch(identityOrVoid(t), 0, commonParameterSequence, i));
@@ -4175,7 +4177,7 @@
pred.set(i, dropArguments(constant(boolean.class, true), 0, commonParameterSequence));
}
if (fini.get(i) == null) {
- fini.set(i, empty(MethodType.methodType(t, commonParameterSequence)));
+ fini.set(i, empty(methodType(t, commonParameterSequence)));
}
}
@@ -4269,7 +4271,8 @@
* @since 9
*/
public static MethodHandle whileLoop(MethodHandle init, MethodHandle pred, MethodHandle body) {
- MethodHandle fin = init == null ? zero(void.class) : identity(init.type().returnType());
+ MethodHandle fin = init == null || init.type().returnType() == void.class ? zero(void.class) :
+ identity(init.type().returnType());
MethodHandle[] checkExit = {null, null, pred, fin};
MethodHandle[] varBody = {init, body};
return loop(checkExit, varBody);
@@ -4335,7 +4338,8 @@
* @since 9
*/
public static MethodHandle doWhileLoop(MethodHandle init, MethodHandle body, MethodHandle pred) {
- MethodHandle fin = init == null ? zero(void.class) : identity(init.type().returnType());
+ MethodHandle fin = init == null || init.type().returnType() == void.class ? zero(void.class) :
+ identity(init.type().returnType());
MethodHandle[] clause = {init, body, pred, fin};
return loop(clause);
}
@@ -4472,8 +4476,8 @@
* @since 9
*/
public static MethodHandle countedLoop(MethodHandle start, MethodHandle end, MethodHandle init, MethodHandle body) {
- MethodHandle returnVar = dropArguments(init == null ? zero(void.class) : identity(init.type().returnType()),
- 0, int.class, int.class);
+ MethodHandle returnVar = dropArguments(init == null || init.type().returnType() == void.class ?
+ zero(void.class) : identity(init.type().returnType()), 0, int.class, int.class);
MethodHandle[] indexVar = {start, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopStep)};
MethodHandle[] loopLimit = {end, null, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopPred), returnVar};
MethodHandle[] bodyClause = {init,
@@ -4485,6 +4489,7 @@
/**
* Constructs a loop that ranges over the elements produced by an {@code Iterator<T>}.
* The iterator will be produced by the evaluation of the {@code iterator} handle.
+ * This handle must have {@link java.util.Iterator} as its return type.
* If this handle is passed as {@code null} the method {@link Iterable#iterator} will be used instead,
* and will be applied to a leading argument of the loop handle.
* Each value produced by the iterator is passed to the {@code body}, which must accept an initial {@code T} parameter.
@@ -4534,7 +4539,7 @@
* assertEquals(reversedList, (List<String>) loop.invoke(list));
* }</pre></blockquote>
* <p>
- * @implSpec The implementation of this method is equivalent to:
+ * @implSpec The implementation of this method is equivalent to (excluding error handling):
* <blockquote><pre>{@code
* MethodHandle iteratedLoop(MethodHandle iterator, MethodHandle init, MethodHandle body) {
* // assume MH_next and MH_hasNext are handles to methods of Iterator
@@ -4550,6 +4555,7 @@
* }</pre></blockquote>
*
* @param iterator a handle to return the iterator to start the loop.
+ * The handle must have {@link java.util.Iterator} as its return type.
* Passing {@code null} will make the loop call {@link Iterable#iterator()} on the first
* incoming value.
* @param init initializer for additional loop state. This determines the loop's result type.
@@ -4565,21 +4571,23 @@
* @since 9
*/
public static MethodHandle iteratedLoop(MethodHandle iterator, MethodHandle init, MethodHandle body) {
- checkIteratedLoop(body);
+ checkIteratedLoop(iterator, body);
+ final boolean voidInit = init == null || init.type().returnType() == void.class;
MethodHandle initit = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_initIterator);
MethodHandle initIterator = iterator == null ?
- initit.asType(initit.type().changeParameterType(0, body.type().parameterType(init == null ? 1 : 2))) :
+ initit.asType(initit.type().changeParameterType(0, body.type().parameterType(voidInit ? 1 : 2))) :
iterator;
Class<?> itype = initIterator.type().returnType();
Class<?> ttype = body.type().parameterType(0);
MethodHandle returnVar =
- dropArguments(init == null ? zero(void.class) : identity(init.type().returnType()), 0, itype);
+ dropArguments(voidInit ? zero(void.class) : identity(init.type().returnType()), 0, itype);
MethodHandle initnx = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_iterateNext);
MethodHandle nextVal = initnx.asType(initnx.type().changeReturnType(ttype));
- MethodHandle[] iterVar = {initIterator, null, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_iteratePred), returnVar};
+ MethodHandle[] iterVar = {initIterator, null, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_iteratePred),
+ returnVar};
MethodHandle[] bodyClause = {init, filterArgument(body, 0, nextVal)};
return loop(iterVar, bodyClause);
@@ -4833,7 +4841,10 @@
}
}
- private static void checkIteratedLoop(MethodHandle body) {
+ private static void checkIteratedLoop(MethodHandle iterator, MethodHandle body) {
+ if (null != iterator && !Iterator.class.isAssignableFrom(iterator.type().returnType())) {
+ throw newIllegalArgumentException("iteratedLoop first argument must have Iterator return type");
+ }
if (null == body) {
throw newIllegalArgumentException("iterated loop body must not be null");
}
--- a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java Thu Apr 21 13:37:31 2016 -0700
@@ -33,7 +33,6 @@
import jdk.internal.misc.Unsafe;
import java.lang.invoke.MethodHandles.Lookup;
-import java.security.AccessController;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -188,14 +187,15 @@
private static final ProxyClassesDumper DUMPER;
static {
- final String strategy = AccessController.doPrivileged(
- new GetPropertyAction("java.lang.invoke.stringConcat"));
- CACHE_ENABLE = Boolean.parseBoolean(AccessController.doPrivileged(
- new GetPropertyAction("java.lang.invoke.stringConcat.cache")));
- DEBUG = Boolean.parseBoolean(AccessController.doPrivileged(
- new GetPropertyAction("java.lang.invoke.stringConcat.debug")));
- final String dumpPath = AccessController.doPrivileged(
- new GetPropertyAction("java.lang.invoke.stringConcat.dumpClasses"));
+ Properties props = GetPropertyAction.getProperties();
+ final String strategy =
+ props.getProperty("java.lang.invoke.stringConcat");
+ CACHE_ENABLE = Boolean.parseBoolean(
+ props.getProperty("java.lang.invoke.stringConcat.cache"));
+ DEBUG = Boolean.parseBoolean(
+ props.getProperty("java.lang.invoke.stringConcat.debug"));
+ final String dumpPath =
+ props.getProperty("java.lang.invoke.stringConcat.dumpClasses");
STRATEGY = (strategy == null) ? DEFAULT_STRATEGY : Strategy.valueOf(strategy);
CACHE = CACHE_ENABLE ? new ConcurrentHashMap<>() : null;
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java Thu Apr 21 13:37:31 2016 -0700
@@ -39,6 +39,7 @@
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import sun.security.action.GetPropertyAction;
/**
* A finder of modules. A {@code ModuleFinder} is used to find modules during
@@ -152,7 +153,7 @@
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
- PrivilegedAction<String> pa = () -> System.getProperty("java.home");
+ PrivilegedAction<String> pa = new GetPropertyAction("java.home");
home = AccessController.doPrivileged(pa);
Permission p = new FilePermission(home + File.separator + "-", "read");
sm.checkPermission(p);
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java Thu Apr 21 13:37:31 2016 -0700
@@ -50,6 +50,7 @@
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection;
import sun.reflect.misc.ReflectUtil;
+import sun.security.action.GetPropertyAction;
import sun.security.util.SecurityConstants;
/**
@@ -581,11 +582,7 @@
}
private static final String DEBUG =
- AccessController.doPrivileged(new PrivilegedAction<>() {
- public String run() {
- return System.getProperty("jdk.proxy.debug", "");
- }
- });
+ GetPropertyAction.getProperty("jdk.proxy.debug", "");
private static boolean isDebug() {
return !DEBUG.isEmpty();
--- a/jdk/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java Thu Apr 21 13:37:31 2016 -0700
@@ -1750,7 +1750,7 @@
* Get or assign the index for a CONSTANT_Float entry.
*/
public short getFloat(float f) {
- return getValue(new Float(f));
+ return getValue(f);
}
/**
--- a/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java Thu Apr 21 13:37:31 2016 -0700
@@ -31,6 +31,7 @@
import java.util.Set;
import java.util.HashSet;
import java.util.Collections;
+import sun.security.action.GetPropertyAction;
/**
* Abstract datagram and multicast socket implementation base class.
@@ -51,9 +52,7 @@
protected InetAddress connectedAddress = null;
private int connectedPort = -1;
- private static final String os = AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("os.name")
- );
+ private static final String os = GetPropertyAction.getProperty("os.name");
/**
* flag set if the native connect() call not to be used
--- a/jdk/src/java.base/share/classes/java/net/InetAddress.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/net/InetAddress.java Thu Apr 21 13:37:31 2016 -0700
@@ -1123,8 +1123,8 @@
*/
private static NameService createNameService() {
- String hostsFileName = AccessController
- .doPrivileged(new GetPropertyAction("jdk.net.hosts.file"));
+ String hostsFileName =
+ GetPropertyAction.getProperty("jdk.net.hosts.file");
NameService theNameService;
if (hostsFileName != null) {
theNameService = new HostsFileNameService(hostsFileName);
@@ -1643,8 +1643,7 @@
* property can vary across implementations of the java.
* classes. The default is an empty String "".
*/
- String prefix = AccessController.doPrivileged(
- new GetPropertyAction("impl.prefix", ""));
+ String prefix = GetPropertyAction.getProperty("impl.prefix", "");
try {
impl = Class.forName("java.net." + prefix + implName).newInstance();
} catch (ClassNotFoundException e) {
--- a/jdk/src/java.base/share/classes/java/net/SocksSocketImpl.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/net/SocksSocketImpl.java Thu Apr 21 13:37:31 2016 -0700
@@ -33,6 +33,7 @@
import sun.net.SocksProxy;
import sun.net.spi.DefaultProxySelector;
import sun.net.www.ParseUtil;
+import sun.security.action.GetPropertyAction;
/* import org.ietf.jgss.*; */
/**
@@ -177,8 +178,7 @@
userName = pw.getUserName();
password = new String(pw.getPassword());
} else {
- userName = java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("user.name"));
+ userName = GetPropertyAction.getProperty("user.name");
}
if (userName == null)
return false;
@@ -1088,8 +1088,7 @@
userName = System.getProperty("user.name");
} catch (SecurityException se) { /* swallow Exception */ }
} else {
- userName = java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("user.name"));
+ userName = GetPropertyAction.getProperty("user.name");
}
return userName;
}
--- a/jdk/src/java.base/share/classes/java/net/URL.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/net/URL.java Thu Apr 21 13:37:31 2016 -0700
@@ -42,6 +42,7 @@
import java.util.ServiceLoader;
import sun.security.util.SecurityConstants;
+import sun.security.action.GetPropertyAction;
/**
* Class {@code URL} represents a Uniform Resource
@@ -1210,12 +1211,8 @@
}
private static URLStreamHandler lookupViaProperty(String protocol) {
- String packagePrefixList = java.security.AccessController.doPrivileged(
- new PrivilegedAction<>() {
- public String run() {
- return System.getProperty(protocolPathProp, null);
- }
- });
+ String packagePrefixList =
+ GetPropertyAction.getProperty(protocolPathProp);
if (packagePrefixList == null) {
// not set
return null;
--- a/jdk/src/java.base/share/classes/java/net/URLConnection.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/net/URLConnection.java Thu Apr 21 13:37:31 2016 -0700
@@ -43,6 +43,7 @@
import java.security.AccessController;
import sun.security.util.SecurityConstants;
import sun.net.www.MessageHeader;
+import sun.security.action.GetPropertyAction;
/**
* The abstract class {@code URLConnection} is the superclass
@@ -1395,8 +1396,8 @@
* is always the last one on the returned package list.
*/
private String getContentHandlerPkgPrefixes() {
- String packagePrefixList = AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction(contentPathProp, ""));
+ String packagePrefixList =
+ GetPropertyAction.getProperty(contentPathProp, "");
if (packagePrefixList != "") {
packagePrefixList += "|";
--- a/jdk/src/java.base/share/classes/java/net/URLEncoder.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/net/URLEncoder.java Thu Apr 21 13:37:31 2016 -0700
@@ -25,19 +25,12 @@
package java.net;
-import java.io.ByteArrayOutputStream;
-import java.io.BufferedWriter;
-import java.io.OutputStreamWriter;
-import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.io.CharArrayWriter;
import java.nio.charset.Charset;
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.UnsupportedCharsetException ;
import java.util.BitSet;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import sun.security.action.GetBooleanAction;
import sun.security.action.GetPropertyAction;
/**
@@ -140,9 +133,7 @@
dontNeedEncoding.set('.');
dontNeedEncoding.set('*');
- dfltEncName = AccessController.doPrivileged(
- new GetPropertyAction("file.encoding")
- );
+ dfltEncName = GetPropertyAction.getProperty("file.encoding");
}
/**
--- a/jdk/src/java.base/share/classes/java/net/URLPermission.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/net/URLPermission.java Thu Apr 21 13:37:31 2016 -0700
@@ -170,7 +170,8 @@
parseURI(getName());
int colon = actions.indexOf(':');
if (actions.lastIndexOf(':') != colon) {
- throw new IllegalArgumentException("invalid actions string");
+ throw new IllegalArgumentException(
+ "Invalid actions string: \"" + actions + "\"");
}
String methods, headers;
@@ -371,7 +372,8 @@
l.add(s);
b = new StringBuilder();
} else if (c == ' ' || c == '\t') {
- throw new IllegalArgumentException("white space not allowed");
+ throw new IllegalArgumentException(
+ "White space not allowed in methods: \"" + methods + "\"");
} else {
if (c >= 'a' && c <= 'z') {
c += 'A' - 'a';
@@ -398,7 +400,8 @@
}
b.append(c);
} else if (c == ' ' || c == '\t') {
- throw new IllegalArgumentException("white space not allowed");
+ throw new IllegalArgumentException(
+ "White space not allowed in headers: \"" + headers + "\"");
} else if (c == '-') {
capitalizeNext = true;
b.append(c);
@@ -423,14 +426,16 @@
int len = url.length();
int delim = url.indexOf(':');
if (delim == -1 || delim + 1 == len) {
- throw new IllegalArgumentException("invalid URL string");
+ throw new IllegalArgumentException(
+ "Invalid URL string: \"" + url + "\"");
}
scheme = url.substring(0, delim).toLowerCase();
this.ssp = url.substring(delim + 1);
if (!ssp.startsWith("//")) {
if (!ssp.equals("*")) {
- throw new IllegalArgumentException("invalid URL string");
+ throw new IllegalArgumentException(
+ "Invalid URL string: \"" + url + "\"");
}
this.authority = new Authority(scheme, "*");
return;
--- a/jdk/src/java.base/share/classes/java/nio/charset/Charset.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/nio/charset/Charset.java Thu Apr 21 13:37:31 2016 -0700
@@ -283,8 +283,8 @@
if (level == null) {
if (!VM.isBooted())
return false;
- bugLevel = level = AccessController.doPrivileged(
- new GetPropertyAction("sun.nio.cs.bugLevel", ""));
+ bugLevel = level =
+ GetPropertyAction.getProperty("sun.nio.cs.bugLevel", "");
}
return level.equals(bl);
}
@@ -609,8 +609,7 @@
public static Charset defaultCharset() {
if (defaultCharset == null) {
synchronized (Charset.class) {
- String csn = AccessController.doPrivileged(
- new GetPropertyAction("file.encoding"));
+ String csn = GetPropertyAction.getProperty("file.encoding");
Charset cs = lookup(csn);
if (cs != null)
defaultCharset = cs;
--- a/jdk/src/java.base/share/classes/java/nio/file/TempFileHelper.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/nio/file/TempFileHelper.java Thu Apr 21 13:37:31 2016 -0700
@@ -28,7 +28,6 @@
import java.util.Set;
import java.util.EnumSet;
import java.security.SecureRandom;
-import static java.security.AccessController.*;
import java.io.IOException;
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.PosixFilePermission;
@@ -47,7 +46,7 @@
// temporary directory location
private static final Path tmpdir =
- Paths.get(doPrivileged(new GetPropertyAction("java.io.tmpdir")));
+ Paths.get(GetPropertyAction.getProperty("java.io.tmpdir"));
private static final boolean isPosix =
FileSystems.getDefault().supportedFileAttributeViews().contains("posix");
--- a/jdk/src/java.base/share/classes/java/text/ChoiceFormat.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/text/ChoiceFormat.java Thu Apr 21 13:37:31 2016 -0700
@@ -437,7 +437,7 @@
if (status.index == start) {
status.errorIndex = furthest;
}
- return new Double(bestNumber);
+ return Double.valueOf(bestNumber);
}
/**
--- a/jdk/src/java.base/share/classes/java/text/DecimalFormat.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/text/DecimalFormat.java Thu Apr 21 13:37:31 2016 -0700
@@ -1996,7 +1996,7 @@
// special case NaN
if (text.regionMatches(pos.index, symbols.getNaN(), 0, symbols.getNaN().length())) {
pos.index = pos.index + symbols.getNaN().length();
- return new Double(Double.NaN);
+ return Double.valueOf(Double.NaN);
}
boolean[] status = new boolean[STATUS_LENGTH];
@@ -2007,19 +2007,19 @@
// special case INFINITY
if (status[STATUS_INFINITE]) {
if (status[STATUS_POSITIVE] == (multiplier >= 0)) {
- return new Double(Double.POSITIVE_INFINITY);
+ return Double.valueOf(Double.POSITIVE_INFINITY);
} else {
- return new Double(Double.NEGATIVE_INFINITY);
+ return Double.valueOf(Double.NEGATIVE_INFINITY);
}
}
if (multiplier == 0) {
if (digitList.isZero()) {
- return new Double(Double.NaN);
+ return Double.valueOf(Double.NaN);
} else if (status[STATUS_POSITIVE]) {
- return new Double(Double.POSITIVE_INFINITY);
+ return Double.valueOf(Double.POSITIVE_INFINITY);
} else {
- return new Double(Double.NEGATIVE_INFINITY);
+ return Double.valueOf(Double.NEGATIVE_INFINITY);
}
}
@@ -2093,8 +2093,8 @@
!isParseIntegerOnly();
}
- return gotDouble ?
- (Number)new Double(doubleResult) : (Number)Long.valueOf(longResult);
+ // cast inside of ?: because of binary numeric promotion, JLS 15.25
+ return gotDouble ? (Number)doubleResult : (Number)longResult;
}
}
--- a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, 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
@@ -1539,8 +1539,8 @@
* <pre>
* Pattern Count Equivalent builder methods
* ------- ----- --------------------------
- * O 1 appendLocalizedOffsetPrefixed(TextStyle.SHORT);
- * OOOO 4 appendLocalizedOffsetPrefixed(TextStyle.FULL);
+ * O 1 appendLocalizedOffset(TextStyle.SHORT);
+ * OOOO 4 appendLocalizedOffset(TextStyle.FULL);
* X 1 appendOffset("+HHmm","Z")
* XX 2 appendOffset("+HHMM","Z")
* XXX 3 appendOffset("+HH:MM","Z")
@@ -3519,9 +3519,7 @@
return false;
}
String gmtText = "GMT"; // TODO: get localized version of 'GMT'
- if (gmtText != null) {
- buf.append(gmtText);
- }
+ buf.append(gmtText);
int totalSecs = Math.toIntExact(offsetSecs);
if (totalSecs != 0) {
int absHours = Math.abs((totalSecs / 3600) % 100); // anything larger than 99 silently dropped
@@ -3565,14 +3563,12 @@
@Override
public int parse(DateTimeParseContext context, CharSequence text, int position) {
int pos = position;
- int end = pos + text.length();
+ int end = text.length();
String gmtText = "GMT"; // TODO: get localized version of 'GMT'
- if (gmtText != null) {
- if (!context.subSequenceEquals(text, pos, gmtText, 0, gmtText.length())) {
+ if (!context.subSequenceEquals(text, pos, gmtText, 0, gmtText.length())) {
return ~position;
}
- pos += gmtText.length();
- }
+ pos += gmtText.length();
// parse normal plus/minus offset
int negative = 0;
if (pos == end) {
--- a/jdk/src/java.base/share/classes/java/util/Locale.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/Locale.java Thu Apr 21 13:37:31 2016 -0700
@@ -45,7 +45,6 @@
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.io.Serializable;
-import java.security.AccessController;
import java.text.MessageFormat;
import java.util.spi.LocaleNameProvider;
@@ -859,11 +858,10 @@
private static Locale initDefault() {
String language, region, script, country, variant;
- language = AccessController.doPrivileged(
- new GetPropertyAction("user.language", "en"));
+ Properties props = GetPropertyAction.getProperties();
+ language = props.getProperty("user.language", "en");
// for compatibility, check for old user.region property
- region = AccessController.doPrivileged(
- new GetPropertyAction("user.region"));
+ region = props.getProperty("user.region");
if (region != null) {
// region can be of form country, country_variant, or _variant
int i = region.indexOf('_');
@@ -876,27 +874,25 @@
}
script = "";
} else {
- script = AccessController.doPrivileged(
- new GetPropertyAction("user.script", ""));
- country = AccessController.doPrivileged(
- new GetPropertyAction("user.country", ""));
- variant = AccessController.doPrivileged(
- new GetPropertyAction("user.variant", ""));
+ script = props.getProperty("user.script", "");
+ country = props.getProperty("user.country", "");
+ variant = props.getProperty("user.variant", "");
}
return getInstance(language, script, country, variant, null);
}
private static Locale initDefault(Locale.Category category) {
+ Properties props = GetPropertyAction.getProperties();
return getInstance(
- AccessController.doPrivileged(
- new GetPropertyAction(category.languageKey, defaultLocale.getLanguage())),
- AccessController.doPrivileged(
- new GetPropertyAction(category.scriptKey, defaultLocale.getScript())),
- AccessController.doPrivileged(
- new GetPropertyAction(category.countryKey, defaultLocale.getCountry())),
- AccessController.doPrivileged(
- new GetPropertyAction(category.variantKey, defaultLocale.getVariant())),
+ props.getProperty(category.languageKey,
+ defaultLocale.getLanguage()),
+ props.getProperty(category.scriptKey,
+ defaultLocale.getScript()),
+ props.getProperty(category.countryKey,
+ defaultLocale.getCountry()),
+ props.getProperty(category.variantKey,
+ defaultLocale.getVariant()),
null);
}
--- a/jdk/src/java.base/share/classes/java/util/PropertyResourceBundle.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/PropertyResourceBundle.java Thu Apr 21 13:37:31 2016 -0700
@@ -43,7 +43,6 @@
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.IOException;
-import java.nio.charset.Charset;
import java.nio.charset.MalformedInputException;
import java.nio.charset.StandardCharsets;
import java.nio.charset.UnmappableCharacterException;
@@ -142,8 +141,8 @@
// Check whether the strict encoding is specified.
// The possible encoding is either "ISO-8859-1" or "UTF-8".
private static final String encoding =
- AccessController.doPrivileged(
- new GetPropertyAction("java.util.PropertyResourceBundle.encoding", ""))
+ GetPropertyAction
+ .getProperty("java.util.PropertyResourceBundle.encoding", "")
.toUpperCase(Locale.ROOT);
/**
--- a/jdk/src/java.base/share/classes/java/util/TimeZone.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/TimeZone.java Thu Apr 21 13:37:31 2016 -0700
@@ -660,14 +660,12 @@
private static synchronized TimeZone setDefaultZone() {
TimeZone tz;
// get the time zone ID from the system properties
- String zoneID = AccessController.doPrivileged(
- new GetPropertyAction("user.timezone"));
+ String zoneID = GetPropertyAction.getProperty("user.timezone");
// if the time zone ID is not set (yet), perform the
// platform to Java time zone ID mapping.
if (zoneID == null || zoneID.isEmpty()) {
- String javaHome = AccessController.doPrivileged(
- new GetPropertyAction("java.home"));
+ String javaHome = GetPropertyAction.getProperty("java.home");
try {
zoneID = getSystemTimeZoneID(javaHome);
if (zoneID == null) {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java Thu Apr 21 13:37:31 2016 -0700
@@ -455,7 +455,7 @@
s = v1 * v1 + v2 * v2;
} while (s >= 1 || s == 0);
double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s)/s);
- nextLocalGaussian.set(new Double(v2 * multiplier));
+ nextLocalGaussian.set(Double.valueOf(v2 * multiplier));
return v1 * multiplier;
}
--- a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java Thu Apr 21 13:37:31 2016 -0700
@@ -34,7 +34,6 @@
import java.util.zip.*;
import java.security.CodeSigner;
import java.security.cert.Certificate;
-import java.security.AccessController;
import java.security.CodeSource;
import jdk.internal.misc.SharedSecrets;
import sun.security.action.GetPropertyAction;
@@ -155,16 +154,16 @@
BASE_VERSION = 8; // one less than lowest version for versioned entries
int runtimeVersion = jdk.Version.current().major();
- String jarVersion = AccessController.doPrivileged(
- new GetPropertyAction("jdk.util.jar.version"));
+ String jarVersion =
+ GetPropertyAction.getProperty("jdk.util.jar.version");
if (jarVersion != null) {
int jarVer = Integer.parseInt(jarVersion);
runtimeVersion = (jarVer > runtimeVersion)
? runtimeVersion : Math.max(jarVer, 0);
}
RUNTIME_VERSION = runtimeVersion;
- String enableMultiRelease = AccessController.doPrivileged(
- new GetPropertyAction("jdk.util.jar.enableMultiRelease", "true"));
+ String enableMultiRelease = GetPropertyAction
+ .getProperty("jdk.util.jar.enableMultiRelease", "true");
switch (enableMultiRelease) {
case "true":
default:
--- a/jdk/src/java.base/share/classes/java/util/jar/Pack200.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/jar/Pack200.java Thu Apr 21 13:37:31 2016 -0700
@@ -29,6 +29,7 @@
import java.io.OutputStream;
import java.io.File;
import java.io.IOException;
+import sun.security.action.GetPropertyAction;
/**
@@ -694,8 +695,7 @@
Class<?> impl = (PACK_PROVIDER.equals(prop))? packerImpl: unpackerImpl;
if (impl == null) {
// The first time, we must decide which class to use.
- implName = java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction(prop,""));
+ implName = GetPropertyAction.getProperty(prop,"");
if (implName != null && !implName.equals(""))
impl = Class.forName(implName);
else if (PACK_PROVIDER.equals(prop))
--- a/jdk/src/java.base/share/classes/java/util/regex/PatternSyntaxException.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/regex/PatternSyntaxException.java Thu Apr 21 13:37:31 2016 -0700
@@ -94,8 +94,7 @@
}
private static final String nl =
- java.security.AccessController
- .doPrivileged(new GetPropertyAction("line.separator"));
+ GetPropertyAction.getProperty("line.separator");
/**
* Returns a multi-line string containing the description of the syntax
--- a/jdk/src/java.base/share/classes/java/util/zip/ZipOutputStream.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/zip/ZipOutputStream.java Thu Apr 21 13:37:31 2016 -0700
@@ -33,6 +33,7 @@
import java.util.HashSet;
import static java.util.zip.ZipConstants64.*;
import static java.util.zip.ZipUtils.*;
+import sun.security.action.GetPropertyAction;
/**
* This class implements an output stream filter for writing files in the
@@ -54,9 +55,7 @@
*/
private static final boolean inhibitZip64 =
Boolean.parseBoolean(
- java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction(
- "jdk.util.zip.inhibitZip64", "false")));
+ GetPropertyAction.getProperty("jdk.util.zip.inhibitZip64"));
private static class XEntry {
final ZipEntry entry;
--- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java Thu Apr 21 13:37:31 2016 -0700
@@ -51,9 +51,9 @@
static final boolean DEBUG;
static {
- String s = java.security.AccessController.doPrivileged(
- new GetPropertyAction("javax.net.debug", "")).toLowerCase(
- Locale.ENGLISH);
+ String s = GetPropertyAction.getProperty("javax.net.debug", "")
+ .toLowerCase(Locale.ENGLISH);
+
DEBUG = s.contains("all") || s.contains("ssl");
}
--- a/jdk/src/java.base/share/classes/jdk/Version.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/jdk/Version.java Thu Apr 21 13:37:31 2016 -0700
@@ -26,8 +26,6 @@
package jdk;
import java.math.BigInteger;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -35,6 +33,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Optional;
+import sun.security.action.GetPropertyAction;
/**
* A representation of the JDK version-string which contains a version
@@ -274,12 +273,7 @@
*/
public static Version current() {
if (current == null) {
- current = parse(AccessController.doPrivileged(
- new PrivilegedAction<>() {
- public String run() {
- return System.getProperty("java.version");
- }
- }));
+ current = parse(GetPropertyAction.getProperty("java.version"));
}
return current;
}
--- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java Thu Apr 21 13:37:31 2016 -0700
@@ -101,10 +101,10 @@
@Override
public FileSystem newFileSystem(URI uri, Map<String, ?> env)
throws IOException {
+ Objects.requireNonNull(env);
checkPermission();
checkUri(uri);
-
- if (env != null && env.containsKey("java.home")) {
+ if (env.containsKey("java.home")) {
return newFileSystem((String)env.get("java.home"), uri, env);
} else {
return new JrtFileSystem(this, env);
--- a/jdk/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java Thu Apr 21 13:37:31 2016 -0700
@@ -52,6 +52,7 @@
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
+import java.util.Properties;
import java.util.Set;
import java.util.Stack;
import java.util.StringTokenizer;
@@ -69,6 +70,7 @@
import jdk.internal.util.jar.JarIndex;
import sun.net.util.URLUtil;
import sun.net.www.ParseUtil;
+import sun.security.action.GetPropertyAction;
/**
* This class is used to maintain a search path of URLs for loading classes
@@ -78,20 +80,15 @@
*/
public class URLClassPath {
private static final String USER_AGENT_JAVA_VERSION = "UA-Java-Version";
- private static final String JAVA_HOME;
private static final String JAVA_VERSION;
private static final boolean DEBUG;
private static final boolean DISABLE_JAR_CHECKING;
static {
- JAVA_HOME = java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("java.home"));
- JAVA_VERSION = java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("java.version"));
- DEBUG = (java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("sun.misc.URLClassPath.debug")) != null);
- String p = java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("sun.misc.URLClassPath.disableJarChecking"));
+ Properties props = GetPropertyAction.getProperties();
+ JAVA_VERSION = props.getProperty("java.version");
+ DEBUG = (props.getProperty("sun.misc.URLClassPath.debug") != null);
+ String p = props.getProperty("sun.misc.URLClassPath.disableJarChecking");
DISABLE_JAR_CHECKING = p != null ? p.equals("true") || p.equals("") : false;
}
--- a/jdk/src/java.base/share/classes/jdk/internal/logger/LoggerFinderLoader.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/jdk/internal/logger/LoggerFinderLoader.java Thu Apr 21 13:37:31 2016 -0700
@@ -33,6 +33,7 @@
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
import sun.security.util.SecurityConstants;
+import sun.security.action.GetPropertyAction;
/**
* Helper class used to load the {@link java.lang.System.LoggerFinder}.
@@ -79,9 +80,8 @@
// Get configuration error policy
private static ErrorPolicy configurationErrorPolicy() {
- final PrivilegedAction<String> getConfigurationErrorPolicy =
- () -> System.getProperty("jdk.logger.finder.error");
- String errorPolicy = AccessController.doPrivileged(getConfigurationErrorPolicy);
+ String errorPolicy =
+ GetPropertyAction.getProperty("jdk.logger.finder.error");
if (errorPolicy == null || errorPolicy.isEmpty()) {
return ErrorPolicy.WARNING;
}
@@ -95,9 +95,8 @@
// Whether multiple provider should be considered as an error.
// This is further submitted to the configuration error policy.
private static boolean ensureSingletonProvider() {
- final PrivilegedAction<Boolean> ensureSingletonProvider =
- () -> Boolean.getBoolean("jdk.logger.finder.singleton");
- return AccessController.doPrivileged(ensureSingletonProvider);
+ return Boolean.parseBoolean(
+ GetPropertyAction.getProperty("jdk.logger.finder.singleton"));
}
private static Iterator<System.LoggerFinder> findLoggerFinderProviders() {
--- a/jdk/src/java.base/share/classes/jdk/internal/logger/SimpleConsoleLogger.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/jdk/internal/logger/SimpleConsoleLogger.java Thu Apr 21 13:37:31 2016 -0700
@@ -55,8 +55,8 @@
PlatformLogger.toPlatformLevel(DEFAULT_LEVEL);
static Level getDefaultLevel() {
- String levelName = AccessController.doPrivileged(
- new GetPropertyAction("jdk.system.logger.level", "INFO"));
+ String levelName = GetPropertyAction
+ .getProperty("jdk.system.logger.level", "INFO");
try {
return Level.valueOf(levelName);
} catch (IllegalArgumentException iae) {
@@ -425,8 +425,8 @@
// Make it easier to wrap Logger...
static private final String[] skips;
static {
- String additionalPkgs = AccessController.doPrivileged(
- new GetPropertyAction("jdk.logger.packages"));
+ String additionalPkgs =
+ GetPropertyAction.getProperty("jdk.logger.packages");
skips = additionalPkgs == null ? new String[0] : additionalPkgs.split(",");
}
@@ -485,7 +485,7 @@
// jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java
// to fail - because that test has a testcase which somehow references
// PlatformLogger and counts the number of generated lambda classes.
- String format = AccessController.doPrivileged(new GetPropertyAction(key));
+ String format = GetPropertyAction.getProperty(key);
if (format == null && defaultPropertyGetter != null) {
format = defaultPropertyGetter.apply(key);
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangInvokeAccess.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangInvokeAccess.java Thu Apr 21 13:37:31 2016 -0700
@@ -30,4 +30,9 @@
* Create a new MemberName instance
*/
Object newMemberName();
+
+ /**
+ * Returns the name for the given MemberName
+ */
+ String getName(Object mname);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaObjectInputStreamAccess.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2016, 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 jdk.internal.misc;
+
+import java.io.ObjectInputStream;
+
+/**
+ * The interface to specify methods for accessing {@code ObjectInputStream}
+ * @author sjiang
+ */
+public interface JavaObjectInputStreamAccess {
+ /**
+ * Sets a descriptor validating.
+ * @param ois stream to have the descriptors validated
+ * @param validator validator used to validate a descriptor.
+ */
+ public void setValidator(ObjectInputStream ois, ObjectStreamClassValidator validator);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/ObjectStreamClassValidator.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016, 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 jdk.internal.misc;
+
+import java.io.ObjectStreamClass;
+
+/**
+ * A callback used by {@code ObjectInputStream} to do descriptor validation.
+ *
+ * @author sjiang
+ */
+public interface ObjectStreamClassValidator {
+ /**
+ * This method will be called by ObjectInputStream to
+ * check a descriptor just before creating an object described by this descriptor.
+ * The object will not be created if this method throws a {@code RuntimeException}.
+ * @param descriptor descriptor to be checked.
+ */
+ public void validateDescriptor(ObjectStreamClass descriptor);
+}
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, 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,9 +29,9 @@
import java.util.jar.JarFile;
import java.io.Console;
import java.io.FileDescriptor;
+import java.io.ObjectInputStream;
import java.security.ProtectionDomain;
import java.security.AccessController;
-import jdk.internal.misc.Unsafe;
/** A repository of "shared secrets", which are a mechanism for
calling implementation-private methods in another package without
@@ -63,6 +63,7 @@
private static JavaAWTAccess javaAWTAccess;
private static JavaAWTFontAccess javaAWTFontAccess;
private static JavaBeansAccess javaBeansAccess;
+ private static JavaObjectInputStreamAccess javaObjectInputStreamAccess;
public static JavaUtilJarAccess javaUtilJarAccess() {
if (javaUtilJarAccess == null) {
@@ -262,4 +263,15 @@
public static void setJavaUtilResourceBundleAccess(JavaUtilResourceBundleAccess access) {
javaUtilResourceBundleAccess = access;
}
+
+ public static JavaObjectInputStreamAccess getJavaObjectInputStreamAccess() {
+ if (javaObjectInputStreamAccess == null) {
+ unsafe.ensureClassInitialized(ObjectInputStream.class);
+ }
+ return javaObjectInputStreamAccess;
+ }
+
+ public static void setJavaObjectInputStreamAccess(JavaObjectInputStreamAccess access) {
+ javaObjectInputStreamAccess = access;
+ }
}
--- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java Thu Apr 21 13:37:31 2016 -0700
@@ -70,6 +70,7 @@
* @author Eric Bruneton
* @author Eugene Kuleshov
*/
+@SuppressWarnings("deprecation") // for Integer(int) constructor
public interface Opcodes {
// ASM API versions
@@ -176,6 +177,8 @@
*/
int F_SAME1 = 4;
+ // For reference comparison purposes, construct new instances
+ // instead of using valueOf() or autoboxing.
Integer TOP = new Integer(0);
Integer INTEGER = new Integer(1);
Integer FLOAT = new Integer(2);
--- a/jdk/src/java.base/share/classes/jdk/internal/reflect/Reflection.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/jdk/internal/reflect/Reflection.java Thu Apr 21 13:37:31 2016 -0700
@@ -27,13 +27,12 @@
import java.lang.reflect.*;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import jdk.internal.HotSpotIntrinsicCandidate;
import jdk.internal.misc.VM;
+import sun.security.action.GetPropertyAction;
/** Common utility routines used by both java.lang and
java.lang.reflect */
@@ -344,15 +343,10 @@
private static void printStackTraceIfNeeded(Throwable e) {
if (!printStackWhenAccessFailsSet && VM.initLevel() >= 1) {
- // can't use method reference here, might be too early in startup
- PrivilegedAction<Boolean> pa = new PrivilegedAction<Boolean>() {
- public Boolean run() {
- String s;
- s = System.getProperty("sun.reflect.debugModuleAccessChecks");
- return (s != null && !s.equalsIgnoreCase("false"));
- }
- };
- printStackWhenAccessFails = AccessController.doPrivileged(pa);
+ String s = GetPropertyAction
+ .getProperty("sun.reflect.debugModuleAccessChecks");
+ printStackWhenAccessFails =
+ (s != null && !s.equalsIgnoreCase("false"));
printStackWhenAccessFailsSet = true;
}
if (printStackWhenAccessFails) {
--- a/jdk/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java Thu Apr 21 13:37:31 2016 -0700
@@ -30,10 +30,11 @@
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
-import java.security.AccessController;
import java.security.Permission;
import java.security.PrivilegedAction;
+import java.util.Properties;
import sun.reflect.misc.ReflectUtil;
+import sun.security.action.GetPropertyAction;
/** <P> The master factory for all reflective objects, both those in
java.lang.reflect (Fields, Methods, Constructors) as well as their
@@ -382,41 +383,37 @@
run, before the system properties are set up. */
private static void checkInitted() {
if (initted) return;
- AccessController.doPrivileged(
- new PrivilegedAction<>() {
- public Void run() {
- // Tests to ensure the system properties table is fully
- // initialized. This is needed because reflection code is
- // called very early in the initialization process (before
- // command-line arguments have been parsed and therefore
- // these user-settable properties installed.) We assume that
- // if System.out is non-null then the System class has been
- // fully initialized and that the bulk of the startup code
- // has been run.
- if (System.out == null) {
- // java.lang.System not yet fully initialized
- return null;
- }
+ // Tests to ensure the system properties table is fully
+ // initialized. This is needed because reflection code is
+ // called very early in the initialization process (before
+ // command-line arguments have been parsed and therefore
+ // these user-settable properties installed.) We assume that
+ // if System.out is non-null then the System class has been
+ // fully initialized and that the bulk of the startup code
+ // has been run.
+
+ if (System.out == null) {
+ // java.lang.System not yet fully initialized
+ return;
+ }
- String val = System.getProperty("sun.reflect.noInflation");
- if (val != null && val.equals("true")) {
- noInflation = true;
- }
+ Properties props = GetPropertyAction.getProperties();
+ String val = props.getProperty("sun.reflect.noInflation");
+ if (val != null && val.equals("true")) {
+ noInflation = true;
+ }
- val = System.getProperty("sun.reflect.inflationThreshold");
- if (val != null) {
- try {
- inflationThreshold = Integer.parseInt(val);
- } catch (NumberFormatException e) {
- throw new RuntimeException("Unable to parse property sun.reflect.inflationThreshold", e);
- }
- }
+ val = props.getProperty("sun.reflect.inflationThreshold");
+ if (val != null) {
+ try {
+ inflationThreshold = Integer.parseInt(val);
+ } catch (NumberFormatException e) {
+ throw new RuntimeException("Unable to parse property sun.reflect.inflationThreshold", e);
+ }
+ }
- initted = true;
- return null;
- }
- });
+ initted = true;
}
private static LangReflectAccess langReflectAccess() {
--- a/jdk/src/java.base/share/classes/module-info.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/module-info.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, 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
@@ -300,9 +300,5 @@
provides java.nio.file.spi.FileSystemProvider with
jdk.internal.jrtfs.JrtFileSystemProvider;
- provides java.security.Provider with sun.security.provider.Sun;
- provides java.security.Provider with sun.security.rsa.SunRsaSign;
- provides java.security.Provider with com.sun.crypto.provider.SunJCE;
- provides java.security.Provider with com.sun.net.ssl.internal.ssl.Provider;
}
--- a/jdk/src/java.base/share/classes/sun/invoke/util/VerifyAccess.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/invoke/util/VerifyAccess.java Thu Apr 21 13:37:31 2016 -0700
@@ -231,22 +231,66 @@
* @param refc the class attempting to make the reference
*/
public static boolean isTypeVisible(Class<?> type, Class<?> refc) {
- if (type == refc) return true; // easy check
+ if (type == refc) {
+ return true; // easy check
+ }
while (type.isArray()) type = type.getComponentType();
- if (type.isPrimitive() || type == Object.class) return true;
- ClassLoader parent = type.getClassLoader();
- if (parent == null) return true;
- ClassLoader child = refc.getClassLoader();
- if (child == null) return false;
- if (parent == child || loadersAreRelated(parent, child, true))
+ if (type.isPrimitive() || type == Object.class) {
return true;
- // Do it the hard way: Look up the type name from the refc loader.
- try {
- Class<?> res = child.loadClass(type.getName());
- return (type == res);
- } catch (ClassNotFoundException ex) {
+ }
+ ClassLoader typeLoader = type.getClassLoader();
+ ClassLoader refcLoader = refc.getClassLoader();
+ if (typeLoader == refcLoader) {
+ return true;
+ }
+ if (refcLoader == null && typeLoader != null) {
return false;
}
+ if (typeLoader == null && type.getName().startsWith("java.")) {
+ // Note: The API for actually loading classes, ClassLoader.defineClass,
+ // guarantees that classes with names beginning "java." cannot be aliased,
+ // because class loaders cannot load them directly.
+ return true;
+ }
+
+ // Do it the hard way: Look up the type name from the refc loader.
+ //
+ // Force the refc loader to report and commit to a particular binding for this type name (type.getName()).
+ //
+ // In principle, this query might force the loader to load some unrelated class,
+ // which would cause this query to fail (and the original caller to give up).
+ // This would be wasted effort, but it is expected to be very rare, occurring
+ // only when an attacker is attempting to create a type alias.
+ // In the normal case, one class loader will simply delegate to the other,
+ // and the same type will be visible through both, with no extra loading.
+ //
+ // It is important to go through Class.forName instead of ClassLoader.loadClass
+ // because Class.forName goes through the JVM system dictionary, which records
+ // the class lookup once for all. This means that even if a not-well-behaved class loader
+ // would "change its mind" about the meaning of the name, the Class.forName request
+ // will use the result cached in the JVM system dictionary. Note that the JVM system dictionary
+ // will record the first successful result. Unsuccessful results are not stored.
+ //
+ // We use doPrivileged in order to allow an unprivileged caller to ask an arbitrary
+ // class loader about the binding of the proposed name (type.getName()).
+ // The looked up type ("res") is compared for equality against the proposed
+ // type ("type") and then is discarded. Thus, the worst that can happen to
+ // the "child" class loader is that it is bothered to load and report a class
+ // that differs from "type"; this happens once due to JVM system dictionary
+ // memoization. And the caller never gets to look at the alternate type binding
+ // ("res"), whether it exists or not.
+ final String name = type.getName();
+ Class<?> res = java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction<>() {
+ public Class<?> run() {
+ try {
+ return Class.forName(name, false, refcLoader);
+ } catch (ClassNotFoundException | LinkageError e) {
+ return null; // Assume the class is not found
+ }
+ }
+ });
+ return (type == res);
}
/**
--- a/jdk/src/java.base/share/classes/sun/net/ResourceManager.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/net/ResourceManager.java Thu Apr 21 13:37:31 2016 -0700
@@ -53,9 +53,8 @@
private static final AtomicInteger numSockets;
static {
- String prop = java.security.AccessController.doPrivileged(
- new GetPropertyAction("sun.net.maxDatagramSockets")
- );
+ String prop =
+ GetPropertyAction.getProperty("sun.net.maxDatagramSockets");
int defmax = DEFAULT_MAX_SOCKETS;
try {
if (prop != null) {
--- a/jdk/src/java.base/share/classes/sun/net/sdp/SdpSupport.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/net/sdp/SdpSupport.java Thu Apr 21 13:37:31 2016 -0700
@@ -31,6 +31,7 @@
import jdk.internal.misc.SharedSecrets;
import jdk.internal.misc.JavaIOFileDescriptorAccess;
+import sun.security.action.GetPropertyAction;
/**
@@ -39,8 +40,7 @@
*/
public final class SdpSupport {
- private static final String os = AccessController
- .doPrivileged(new sun.security.action.GetPropertyAction("os.name"));
+ private static final String os = GetPropertyAction.getProperty("os.name");
private static final boolean isSupported = (os.equals("SunOS") || (os.equals("Linux")));
private static final JavaIOFileDescriptorAccess fdAccess =
SharedSecrets.getJavaIOFileDescriptorAccess();
--- a/jdk/src/java.base/share/classes/sun/net/smtp/SmtpClient.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/net/smtp/SmtpClient.java Thu Apr 21 13:37:31 2016 -0700
@@ -25,10 +25,10 @@
package sun.net.smtp;
-import java.util.StringTokenizer;
import java.io.*;
import java.net.*;
import sun.net.TransferProtocolClient;
+import sun.security.action.GetPropertyAction;
/**
* This class implements the SMTP client.
@@ -157,8 +157,7 @@
}
try {
String s;
- mailhost = java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("mail.host"));
+ mailhost = GetPropertyAction.getProperty("mail.host");
if (mailhost != null) {
openServer(mailhost);
return;
@@ -184,8 +183,7 @@
setConnectTimeout(to);
try {
String s;
- mailhost = java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("mail.host"));
+ mailhost = GetPropertyAction.getProperty("mail.host");
if (mailhost != null) {
openServer(mailhost);
return;
--- a/jdk/src/java.base/share/classes/sun/net/www/MimeLauncher.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/net/www/MimeLauncher.java Thu Apr 21 13:37:31 2016 -0700
@@ -27,6 +27,7 @@
import java.net.URL;
import java.io.*;
import java.util.StringTokenizer;
+import sun.security.action.GetPropertyAction;
class MimeLauncher extends Thread {
java.net.URLConnection uc;
@@ -182,8 +183,7 @@
}
String execPathList;
- execPathList = java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("exec.path"));
+ execPathList = GetPropertyAction.getProperty("exec.path");
if (execPathList == null) {
// exec.path property not set
return false;
--- a/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java Thu Apr 21 13:37:31 2016 -0700
@@ -28,6 +28,7 @@
import java.io.*;
import java.net.*;
import java.util.Locale;
+import java.util.Properties;
import sun.net.NetworkClient;
import sun.net.ProgressSource;
import sun.net.www.MessageHeader;
@@ -37,6 +38,7 @@
import sun.net.www.protocol.http.HttpURLConnection;
import sun.util.logging.PlatformLogger;
import static sun.net.www.protocol.http.HttpURLConnection.TunnelState.*;
+import sun.security.action.GetPropertyAction;
/**
* @author Herb Jellinek
@@ -143,20 +145,18 @@
}
static {
- String keepAlive = java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("http.keepAlive"));
-
- String retryPost = java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("sun.net.http.retryPost"));
+ Properties props = GetPropertyAction.getProperties();
+ String keepAlive = props.getProperty("http.keepAlive");
+ String retryPost = props.getProperty("sun.net.http.retryPost");
if (keepAlive != null) {
- keepAliveProp = Boolean.valueOf(keepAlive).booleanValue();
+ keepAliveProp = Boolean.parseBoolean(keepAlive);
} else {
keepAliveProp = true;
}
if (retryPost != null) {
- retryPostProp = Boolean.valueOf(retryPost).booleanValue();
+ retryPostProp = Boolean.parseBoolean(retryPost);
} else
retryPostProp = true;
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java Thu Apr 21 13:37:31 2016 -0700
@@ -46,6 +46,7 @@
import java.util.StringTokenizer;
import java.util.Iterator;
import java.security.Permission;
+import java.util.Properties;
import sun.net.NetworkClient;
import sun.net.www.MessageHeader;
import sun.net.www.MeteredStream;
@@ -277,11 +278,10 @@
if (user == null) {
user = "anonymous";
- String vers = java.security.AccessController.doPrivileged(
- new GetPropertyAction("java.version"));
- password = java.security.AccessController.doPrivileged(
- new GetPropertyAction("ftp.protocol.user",
- "Java" + vers + "@"));
+ Properties props = GetPropertyAction.getProperties();
+ String vers = props.getProperty("java.version");
+ password = props.getProperty("ftp.protocol.user",
+ "Java" + vers + "@");
}
try {
ftp = FtpClient.create();
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java Thu Apr 21 13:37:31 2016 -0700
@@ -25,9 +25,10 @@
package sun.net.www.protocol.http;
-import sun.net.www.*;
import java.util.Iterator;
import java.util.HashMap;
+import sun.net.www.*;
+import sun.security.action.GetPropertyAction;
/**
* This class is used to parse the information in WWW-Authenticate: and Proxy-Authenticate:
@@ -93,8 +94,7 @@
}
static {
- authPref = java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("http.auth.preference"));
+ authPref = GetPropertyAction.getProperty("http.auth.preference");
// http.auth.preference can be set to SPNEGO or Kerberos.
// In fact they means "Negotiate with SPNEGO" and "Negotiate with
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Thu Apr 21 13:37:31 2016 -0700
@@ -52,7 +52,6 @@
import java.security.PrivilegedExceptionAction;
import java.security.PrivilegedActionException;
import java.io.*;
-import java.net.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
@@ -78,12 +77,15 @@
import java.util.TimeZone;
import java.net.MalformedURLException;
import java.nio.ByteBuffer;
+import java.util.Properties;
import static sun.net.www.protocol.http.AuthScheme.BASIC;
import static sun.net.www.protocol.http.AuthScheme.DIGEST;
import static sun.net.www.protocol.http.AuthScheme.NTLM;
import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE;
import static sun.net.www.protocol.http.AuthScheme.KERBEROS;
import static sun.net.www.protocol.http.AuthScheme.UNKNOWN;
+import sun.security.action.GetIntegerAction;
+import sun.security.action.GetPropertyAction;
/**
* A class to represent an HTTP connection to a remote object.
@@ -205,46 +207,38 @@
};
static {
- maxRedirects = java.security.AccessController.doPrivileged(
- new sun.security.action.GetIntegerAction(
- "http.maxRedirects", defaultmaxRedirects)).intValue();
- version = java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("java.version"));
- String agent = java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("http.agent"));
+ Properties props = GetPropertyAction.getProperties();
+ maxRedirects = GetIntegerAction.getProperty("http.maxRedirects",
+ defaultmaxRedirects);
+ version = props.getProperty("java.version");
+ String agent = props.getProperty("http.agent");
if (agent == null) {
agent = "Java/"+version;
} else {
agent = agent + " Java/"+version;
}
userAgent = agent;
- validateProxy = java.security.AccessController.doPrivileged(
- new sun.security.action.GetBooleanAction(
- "http.auth.digest.validateProxy")).booleanValue();
- validateServer = java.security.AccessController.doPrivileged(
- new sun.security.action.GetBooleanAction(
- "http.auth.digest.validateServer")).booleanValue();
-
- enableESBuffer = java.security.AccessController.doPrivileged(
- new sun.security.action.GetBooleanAction(
- "sun.net.http.errorstream.enableBuffering")).booleanValue();
- timeout4ESBuffer = java.security.AccessController.doPrivileged(
- new sun.security.action.GetIntegerAction(
- "sun.net.http.errorstream.timeout", 300)).intValue();
+ validateProxy = Boolean.parseBoolean(
+ props.getProperty("http.auth.digest.validateProxy"));
+ validateServer = Boolean.parseBoolean(
+ props.getProperty("http.auth.digest.validateServer"));
+
+ enableESBuffer = Boolean.parseBoolean(
+ props.getProperty("sun.net.http.errorstream.enableBuffering"));
+ timeout4ESBuffer = GetIntegerAction
+ .getProperty("sun.net.http.errorstream.timeout", 300);
if (timeout4ESBuffer <= 0) {
timeout4ESBuffer = 300; // use the default
}
- bufSize4ES = java.security.AccessController.doPrivileged(
- new sun.security.action.GetIntegerAction(
- "sun.net.http.errorstream.bufferSize", 4096)).intValue();
+ bufSize4ES = GetIntegerAction
+ .getProperty("sun.net.http.errorstream.bufferSize", 4096);
if (bufSize4ES <= 0) {
bufSize4ES = 4096; // use the default
}
- allowRestrictedHeaders = java.security.AccessController.doPrivileged(
- new sun.security.action.GetBooleanAction(
- "sun.net.http.allowRestrictedHeaders")).booleanValue();
+ allowRestrictedHeaders = Boolean.parseBoolean(
+ props.getProperty("sun.net.http.allowRestrictedHeaders"));
if (!allowRestrictedHeaders) {
restrictedHeaderSet = new HashSet<>(restrictedHeaders.length);
for (int i=0; i < restrictedHeaders.length; i++) {
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java Thu Apr 21 13:37:31 2016 -0700
@@ -41,7 +41,6 @@
import java.security.cert.*;
import java.util.StringTokenizer;
import java.util.Vector;
-import java.security.AccessController;
import javax.security.auth.x500.X500Principal;
@@ -139,8 +138,8 @@
// If ciphers are assigned, sort them into an array.
//
String ciphers [];
- String cipherString = AccessController.doPrivileged(
- new GetPropertyAction("https.cipherSuites"));
+ String cipherString =
+ GetPropertyAction.getProperty("https.cipherSuites");
if (cipherString == null || "".equals(cipherString)) {
ciphers = null;
@@ -163,8 +162,8 @@
// If protocols are assigned, sort them into an array.
//
String protocols [];
- String protocolString = AccessController.doPrivileged(
- new GetPropertyAction("https.protocols"));
+ String protocolString =
+ GetPropertyAction.getProperty("https.protocols");
if (protocolString == null || "".equals(protocolString)) {
protocols = null;
@@ -184,8 +183,7 @@
}
private String getUserAgent() {
- String userAgent = java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("https.agent"));
+ String userAgent = GetPropertyAction.getProperty("https.agent");
if (userAgent == null || userAgent.length() == 0) {
userAgent = "JSSE";
}
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java Thu Apr 21 13:37:31 2016 -0700
@@ -32,10 +32,7 @@
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
-import java.security.AccessController;
import java.security.Permission;
-import java.security.PrivilegedAction;
-import java.util.List;
import jdk.internal.jimage.ImageLocation;
import jdk.internal.jimage.ImageReader;
@@ -45,6 +42,7 @@
import jdk.internal.loader.Resource;
import sun.net.www.ParseUtil;
import sun.net.www.URLConnection;
+import sun.security.action.GetPropertyAction;
/**
* URLConnection implementation that can be used to connect to resources
@@ -163,11 +161,7 @@
public Permission getPermission() throws IOException {
Permission p = permission;
if (p == null) {
- // using lambda expression here leads to recursive initialization
- PrivilegedAction<String> pa = new PrivilegedAction<String>() {
- public String run() { return System.getProperty("java.home"); }
- };
- String home = AccessController.doPrivileged(pa);
+ String home = GetPropertyAction.getProperty("java.home");
p = new FilePermission(home + File.separator + "-", "read");
permission = p;
}
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/netdoc/Handler.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/netdoc/Handler.java Thu Apr 21 13:37:31 2016 -0700
@@ -40,6 +40,7 @@
import java.net.URLStreamHandler;
import java.io.InputStream;
import java.io.IOException;
+import sun.security.action.GetPropertyAction;
public class Handler extends URLStreamHandler {
static URL base;
@@ -54,12 +55,10 @@
URLConnection uc = null;
URL ru;
- Boolean tmp = java.security.AccessController.doPrivileged(
- new sun.security.action.GetBooleanAction("newdoc.localonly"));
- boolean localonly = tmp.booleanValue();
+ boolean localonly = Boolean.parseBoolean(
+ GetPropertyAction.getProperty("newdoc.localonly"));
- String docurl = java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("doc.url"));
+ String docurl = GetPropertyAction.getProperty("doc.url");
String file = u.getFile();
if (!localonly) {
--- a/jdk/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java Thu Apr 21 13:37:31 2016 -0700
@@ -1019,9 +1019,8 @@
if (!propertyChecked) {
synchronized (FileChannelImpl.class) {
if (!propertyChecked) {
- String value = AccessController.doPrivileged(
- new GetPropertyAction(
- "sun.nio.ch.disableSystemWideOverlappingFileLockCheck"));
+ String value = GetPropertyAction.getProperty(
+ "sun.nio.ch.disableSystemWideOverlappingFileLockCheck");
isSharedFileLockTable = ((value == null) || value.equals("false"));
propertyChecked = true;
}
--- a/jdk/src/java.base/share/classes/sun/nio/ch/Net.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/Net.java Thu Apr 21 13:37:31 2016 -0700
@@ -33,6 +33,7 @@
import java.security.AccessController;
import java.security.PrivilegedAction;
import sun.net.ExtendedOptionsImpl;
+import sun.security.action.GetPropertyAction;
public class Net {
@@ -382,13 +383,8 @@
}
public static boolean isFastTcpLoopbackRequested() {
- String loopbackProp = java.security.AccessController.doPrivileged(
- new PrivilegedAction<String>() {
- @Override
- public String run() {
- return System.getProperty("jdk.net.useFastTcpLoopback");
- }
- });
+ String loopbackProp =
+ GetPropertyAction.getProperty("jdk.net.useFastTcpLoopback");
boolean enable;
if ("".equals(loopbackProp)) {
enable = true;
@@ -647,16 +643,9 @@
int availLevel = isExclusiveBindAvailable();
if (availLevel >= 0) {
String exclBindProp =
- java.security.AccessController.doPrivileged(
- new PrivilegedAction<String>() {
- @Override
- public String run() {
- return System.getProperty(
- "sun.net.useExclusiveBind");
- }
- });
+ GetPropertyAction.getProperty("sun.net.useExclusiveBind");
if (exclBindProp != null) {
- exclusiveBind = exclBindProp.length() == 0 ?
+ exclusiveBind = exclBindProp.isEmpty() ?
true : Boolean.parseBoolean(exclBindProp);
} else if (availLevel == 1) {
exclusiveBind = true;
--- a/jdk/src/java.base/share/classes/sun/nio/ch/Util.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/Util.java Thu Apr 21 13:37:31 2016 -0700
@@ -64,13 +64,7 @@
* for potential future-proofing.
*/
private static long getMaxCachedBufferSize() {
- String s = java.security.AccessController.doPrivileged(
- new PrivilegedAction<String>() {
- @Override
- public String run() {
- return System.getProperty("jdk.nio.maxCachedBufferSize");
- }
- });
+ String s = GetPropertyAction.getProperty("jdk.nio.maxCachedBufferSize");
if (s != null) {
try {
long m = Long.parseLong(s);
@@ -471,8 +465,7 @@
if (bugLevel == null) {
if (!jdk.internal.misc.VM.isBooted())
return false;
- String value = AccessController.doPrivileged(
- new GetPropertyAction("sun.nio.ch.bugLevel"));
+ String value = GetPropertyAction.getProperty("sun.nio.ch.bugLevel");
bugLevel = (value != null) ? value : "";
}
return bugLevel.equals(bl);
--- a/jdk/src/java.base/share/classes/sun/nio/cs/StandardCharsets.java.template Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/nio/cs/StandardCharsets.java.template Thu Apr 21 13:37:31 2016 -0700
@@ -34,8 +34,7 @@
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
+import sun.security.action.GetPropertyAction;
public class StandardCharsets extends CharsetProvider {
@@ -201,15 +200,7 @@
}
private static String getProperty(String key) {
- // this method may be called during initialization of
- // system class loader and thus not using lambda
- return AccessController.doPrivileged(
- new PrivilegedAction<String>() {
- @Override
- public String run() {
- return System.getProperty(key);
- }
- });
+ return GetPropertyAction.getProperty(key);
}
--- a/jdk/src/java.base/share/classes/sun/nio/fs/Util.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/nio/fs/Util.java Thu Apr 21 13:37:31 2016 -0700
@@ -28,8 +28,7 @@
import java.util.*;
import java.nio.file.*;
import java.nio.charset.Charset;
-import java.security.*;
-import sun.security.action.*;
+import sun.security.action.GetPropertyAction;
/**
* Utility methods
@@ -39,7 +38,7 @@
private Util() { }
private static final Charset jnuEncoding = Charset.forName(
- AccessController.doPrivileged(new GetPropertyAction("sun.jnu.encoding")));
+ GetPropertyAction.getProperty("sun.jnu.encoding"));
/**
* Returns {@code Charset} corresponding to the sun.jnu.encoding property
--- a/jdk/src/java.base/share/classes/sun/security/action/GetIntegerAction.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/action/GetIntegerAction.java Thu Apr 21 13:37:31 2016 -0700
@@ -25,6 +25,8 @@
package sun.security.action;
+import java.security.AccessController;
+
/**
* A convenience class for retrieving the integer value of a system property
* as a privileged action.
@@ -67,7 +69,7 @@
implements java.security.PrivilegedAction<Integer> {
private String theProp;
private int defaultVal;
- private boolean defaultSet = false;
+ private boolean defaultSet;
/**
* Constructor that takes the name of the system property whose integer
@@ -110,4 +112,39 @@
return defaultVal;
return value;
}
+
+ /**
+ * Convenience method to get a property without going through doPrivileged
+ * if no security manager is present. This is unsafe for inclusion in a
+ * public API but allowable here since this class is now encapsulated.
+ *
+ * @param theProp the name of the system property.
+ */
+ public static Integer getProperty(String theProp) {
+ if (System.getSecurityManager() == null) {
+ return Integer.getInteger(theProp);
+ } else {
+ return AccessController.doPrivileged(
+ new GetIntegerAction(theProp));
+ }
+ }
+
+ /**
+ * Convenience method to get a property without going through doPrivileged
+ * if no security manager is present. This is unsafe for inclusion in a
+ * public API but allowable here since this class is now encapsulated.
+ *
+ * @param theProp the name of the system property.
+ * @param defaultVal the default value.
+ */
+ public static Integer getProperty(String theProp, int defaultVal) {
+ Integer value;
+ if (System.getSecurityManager() == null) {
+ value = Integer.getInteger(theProp);
+ } else {
+ value = AccessController.doPrivileged(
+ new GetIntegerAction(theProp));
+ }
+ return (value != null) ? value : defaultVal;
+ }
}
--- a/jdk/src/java.base/share/classes/sun/security/action/GetPropertyAction.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/action/GetPropertyAction.java Thu Apr 21 13:37:31 2016 -0700
@@ -25,6 +25,10 @@
package sun.security.action;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Properties;
+
/**
* A convenience class for retrieving the string value of a system
* property as a privileged action.
@@ -46,8 +50,7 @@
* @since 1.2
*/
-public class GetPropertyAction
- implements java.security.PrivilegedAction<String> {
+public class GetPropertyAction implements PrivilegedAction<String> {
private String theProp;
private String defaultVal;
@@ -84,4 +87,57 @@
String value = System.getProperty(theProp);
return (value == null) ? defaultVal : value;
}
+
+ /**
+ * Convenience method to get a property without going through doPrivileged
+ * if no security manager is present. This is unsafe for inclusion in a
+ * public API but allowable here since this class is now encapsulated.
+ *
+ * @param theProp the name of the system property.
+ */
+ public static String getProperty(String theProp) {
+ if (System.getSecurityManager() == null) {
+ return System.getProperty(theProp);
+ } else {
+ return AccessController.doPrivileged(
+ new GetPropertyAction(theProp));
+ }
+ }
+
+ /**
+ * Convenience method to get a property without going through doPrivileged
+ * if no security manager is present. This is unsafe for inclusion in a
+ * public API but allowable here since this class is now encapsulated.
+ *
+ * @param theProp the name of the system property.
+ * @param defaultVal the default value.
+ */
+ public static String getProperty(String theProp, String defaultVal) {
+ if (System.getSecurityManager() == null) {
+ return System.getProperty(theProp, defaultVal);
+ } else {
+ return AccessController.doPrivileged(
+ new GetPropertyAction(theProp, defaultVal));
+ }
+ }
+
+ /**
+ * Convenience method to call <code>System.getProperties</code> without
+ * having to go through doPrivileged if no security manager is present.
+ * This is unsafe for inclusion in a public API but allowable here since
+ * this class is now encapsulated.
+ */
+ public static Properties getProperties() {
+ if (System.getSecurityManager() == null) {
+ return System.getProperties();
+ } else {
+ return AccessController.doPrivileged(
+ new PrivilegedAction<Properties>() {
+ public Properties run() {
+ return System.getProperties();
+ }
+ }
+ );
+ }
+ }
}
--- a/jdk/src/java.base/share/classes/sun/security/jca/ProviderConfig.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/jca/ProviderConfig.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, 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
@@ -236,9 +236,8 @@
if (debug != null) {
debug.println("Loading provider " + ProviderConfig.this);
}
- ProviderLoader pl = new ProviderLoader();
try {
- Provider p = pl.load(provName);
+ Provider p = ProviderLoader.INSTANCE.load(provName);
if (p != null) {
if (hasArgument()) {
p = p.configure(argument);
@@ -303,9 +302,11 @@
// Inner class for loading security providers listed in java.security file
private static final class ProviderLoader {
+ static final ProviderLoader INSTANCE = new ProviderLoader();
+
private final ServiceLoader<Provider> services;
- ProviderLoader() {
+ private ProviderLoader() {
// VM should already been booted at this point, if not
// - Only providers in java.base should be loaded, don't use
// ServiceLoader
--- a/jdk/src/java.base/share/classes/sun/security/provider/DSA.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/provider/DSA.java Thu Apr 21 13:37:31 2016 -0700
@@ -106,6 +106,18 @@
this.p1363Format = p1363Format;
}
+ private static void checkKey(DSAParams params, int digestLen, String mdAlgo)
+ throws InvalidKeyException {
+ // FIPS186-3 states in sec4.2 that a hash function which provides
+ // a lower security strength than the (L, N) pair ordinarily should
+ // not be used.
+ int valueN = params.getQ().bitLength();
+ if (valueN > digestLen) {
+ throw new InvalidKeyException("The security strength of " +
+ mdAlgo + " digest algorithm is not sufficient for this key size");
+ }
+ }
+
/**
* Initialize the DSA object with a DSA private key.
*
@@ -130,6 +142,12 @@
throw new InvalidKeyException("DSA private key lacks parameters");
}
+ // check key size against hash output size for signing
+ // skip this check for verification to minimize impact on existing apps
+ if (md.getAlgorithm() != "NullDigest20") {
+ checkKey(params, md.getDigestLength()*8, md.getAlgorithm());
+ }
+
this.params = params;
this.presetX = priv.getX();
this.presetY = null;
@@ -160,7 +178,6 @@
if (params == null) {
throw new InvalidKeyException("DSA public key lacks parameters");
}
-
this.params = params;
this.presetY = pub.getY();
this.presetX = null;
@@ -406,20 +423,13 @@
return t5.mod(q);
}
- // NOTE: This following impl is defined in FIPS 186-3 AppendixB.2.2.
- // Original DSS algos such as SHA1withDSA and RawDSA uses a different
- // algorithm defined in FIPS 186-1 Sec3.2, and thus need to override this.
+ // NOTE: This following impl is defined in FIPS 186-4 AppendixB.2.1.
protected BigInteger generateK(BigInteger q) {
SecureRandom random = getSigningRandom();
- byte[] kValue = new byte[q.bitLength()/8];
+ byte[] kValue = new byte[(q.bitLength() + 7)/8 + 8];
- while (true) {
- random.nextBytes(kValue);
- BigInteger k = new BigInteger(1, kValue).mod(q);
- if (k.signum() > 0 && k.compareTo(q) < 0) {
- return k;
- }
- }
+ random.nextBytes(kValue);
+ return new BigInteger(1, kValue).mod(q.subtract(BigInteger.ONE)).add(BigInteger.ONE);
}
// Use the application-specified SecureRandom Object if provided.
@@ -504,222 +514,10 @@
}
}
- static class LegacyDSA extends DSA {
- /* The random seed used to generate k */
- private int[] kSeed;
- /* The random seed used to generate k (specified by application) */
- private byte[] kSeedAsByteArray;
- /*
- * The random seed used to generate k
- * (prevent the same Kseed from being used twice in a row
- */
- private int[] kSeedLast;
-
- public LegacyDSA(MessageDigest md) throws NoSuchAlgorithmException {
- this(md, false);
- }
-
- private LegacyDSA(MessageDigest md, boolean p1363Format)
- throws NoSuchAlgorithmException {
- super(md, p1363Format);
- }
-
- @Deprecated
- protected void engineSetParameter(String key, Object param) {
- if (key.equals("KSEED")) {
- if (param instanceof byte[]) {
- kSeed = byteArray2IntArray((byte[])param);
- kSeedAsByteArray = (byte[])param;
- } else {
- debug("unrecognized param: " + key);
- throw new InvalidParameterException("kSeed not a byte array");
- }
- } else {
- throw new InvalidParameterException("Unsupported parameter");
- }
- }
-
- @Deprecated
- protected Object engineGetParameter(String key) {
- if (key.equals("KSEED")) {
- return kSeedAsByteArray;
- } else {
- return null;
- }
- }
-
- /*
- * Please read bug report 4044247 for an alternative, faster,
- * NON-FIPS approved method to generate K
- */
- @Override
- protected BigInteger generateK(BigInteger q) {
- BigInteger k = null;
-
- // The application specified a kSeed for us to use.
- // Note: we dis-allow usage of the same Kseed twice in a row
- if (kSeed != null && !Arrays.equals(kSeed, kSeedLast)) {
- k = generateKUsingKSeed(kSeed, q);
- if (k.signum() > 0 && k.compareTo(q) < 0) {
- kSeedLast = kSeed.clone();
- return k;
- }
- }
-
- // The application did not specify a Kseed for us to use.
- // We'll generate a new Kseed by getting random bytes from
- // a SecureRandom object.
- SecureRandom random = getSigningRandom();
-
- while (true) {
- int[] seed = new int[5];
-
- for (int i = 0; i < 5; i++) seed[i] = random.nextInt();
-
- k = generateKUsingKSeed(seed, q);
- if (k.signum() > 0 && k.compareTo(q) < 0) {
- kSeedLast = seed;
- return k;
- }
- }
- }
-
- /**
- * Compute k for the DSA signature as defined in the original DSS,
- * i.e. FIPS186.
- *
- * @param seed the seed for generating k. This seed should be
- * secure. This is what is referred to as the KSEED in the DSA
- * specification.
- *
- * @param g the g parameter from the DSA key pair.
- */
- private BigInteger generateKUsingKSeed(int[] seed, BigInteger q) {
-
- // check out t in the spec.
- int[] t = { 0xEFCDAB89, 0x98BADCFE, 0x10325476,
- 0xC3D2E1F0, 0x67452301 };
- //
- int[] tmp = SHA_7(seed, t);
- byte[] tmpBytes = new byte[tmp.length * 4];
- for (int i = 0; i < tmp.length; i++) {
- int k = tmp[i];
- for (int j = 0; j < 4; j++) {
- tmpBytes[(i * 4) + j] = (byte) (k >>> (24 - (j * 8)));
- }
- }
- BigInteger k = new BigInteger(1, tmpBytes).mod(q);
- return k;
- }
-
- // Constants for each round
- private static final int round1_kt = 0x5a827999;
- private static final int round2_kt = 0x6ed9eba1;
- private static final int round3_kt = 0x8f1bbcdc;
- private static final int round4_kt = 0xca62c1d6;
-
- /**
- * Computes set 1 thru 7 of SHA-1 on m1. */
- static int[] SHA_7(int[] m1, int[] h) {
-
- int[] W = new int[80];
- System.arraycopy(m1,0,W,0,m1.length);
- int temp = 0;
-
- for (int t = 16; t <= 79; t++){
- temp = W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16];
- W[t] = ((temp << 1) | (temp >>>(32 - 1)));
- }
-
- int a = h[0],b = h[1],c = h[2], d = h[3], e = h[4];
- for (int i = 0; i < 20; i++) {
- temp = ((a<<5) | (a>>>(32-5))) +
- ((b&c)|((~b)&d))+ e + W[i] + round1_kt;
- e = d;
- d = c;
- c = ((b<<30) | (b>>>(32-30)));
- b = a;
- a = temp;
- }
-
- // Round 2
- for (int i = 20; i < 40; i++) {
- temp = ((a<<5) | (a>>>(32-5))) +
- (b ^ c ^ d) + e + W[i] + round2_kt;
- e = d;
- d = c;
- c = ((b<<30) | (b>>>(32-30)));
- b = a;
- a = temp;
- }
-
- // Round 3
- for (int i = 40; i < 60; i++) {
- temp = ((a<<5) | (a>>>(32-5))) +
- ((b&c)|(b&d)|(c&d)) + e + W[i] + round3_kt;
- e = d;
- d = c;
- c = ((b<<30) | (b>>>(32-30)));
- b = a;
- a = temp;
- }
-
- // Round 4
- for (int i = 60; i < 80; i++) {
- temp = ((a<<5) | (a>>>(32-5))) +
- (b ^ c ^ d) + e + W[i] + round4_kt;
- e = d;
- d = c;
- c = ((b<<30) | (b>>>(32-30)));
- b = a;
- a = temp;
- }
- int[] md = new int[5];
- md[0] = h[0] + a;
- md[1] = h[1] + b;
- md[2] = h[2] + c;
- md[3] = h[3] + d;
- md[4] = h[4] + e;
- return md;
- }
-
- /*
- * Utility routine for converting a byte array into an int array
- */
- private int[] byteArray2IntArray(byte[] byteArray) {
-
- int j = 0;
- byte[] newBA;
- int mod = byteArray.length % 4;
-
- // guarantee that the incoming byteArray is a multiple of 4
- // (pad with 0's)
- switch (mod) {
- case 3: newBA = new byte[byteArray.length + 1]; break;
- case 2: newBA = new byte[byteArray.length + 2]; break;
- case 1: newBA = new byte[byteArray.length + 3]; break;
- default: newBA = new byte[byteArray.length + 0]; break;
- }
- System.arraycopy(byteArray, 0, newBA, 0, byteArray.length);
-
- // copy each set of 4 bytes in the byte array into an integer
- int[] newSeed = new int[newBA.length / 4];
- for (int i = 0; i < newBA.length; i += 4) {
- newSeed[j] = newBA[i + 3] & 0xFF;
- newSeed[j] |= (newBA[i + 2] << 8) & 0xFF00;
- newSeed[j] |= (newBA[i + 1] << 16) & 0xFF0000;
- newSeed[j] |= (newBA[i + 0] << 24) & 0xFF000000;
- j++;
- }
-
- return newSeed;
- }
- }
-
/**
* Standard SHA1withDSA implementation.
*/
- public static final class SHA1withDSA extends LegacyDSA {
+ public static final class SHA1withDSA extends DSA {
public SHA1withDSA() throws NoSuchAlgorithmException {
super(MessageDigest.getInstance("SHA-1"));
}
@@ -728,7 +526,7 @@
/**
* SHA1withDSA implementation that uses the IEEE P1363 format.
*/
- public static final class SHA1withDSAinP1363Format extends LegacyDSA {
+ public static final class SHA1withDSAinP1363Format extends DSA {
public SHA1withDSAinP1363Format() throws NoSuchAlgorithmException {
super(MessageDigest.getInstance("SHA-1"), true);
}
@@ -741,7 +539,7 @@
* not, a SignatureException is thrown when sign()/verify() is called
* per JCA spec.
*/
- static class Raw extends LegacyDSA {
+ static class Raw extends DSA {
// Internal special-purpose MessageDigest impl for RawDSA
// Only override whatever methods used
// NOTE: no clone support
--- a/jdk/src/java.base/share/classes/sun/security/provider/DSAKeyFactory.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/provider/DSAKeyFactory.java Thu Apr 21 13:37:31 2016 -0700
@@ -70,8 +70,7 @@
* By default this is false.
* This incompatibility was introduced by 4532506.
*/
- String prop = AccessController.doPrivileged
- (new GetPropertyAction(SERIAL_PROP, null));
+ String prop = GetPropertyAction.getProperty(SERIAL_PROP);
SERIAL_INTEROP = "true".equalsIgnoreCase(prop);
}
--- a/jdk/src/java.base/share/classes/sun/security/rsa/RSAKeyFactory.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/rsa/RSAKeyFactory.java Thu Apr 21 13:37:31 2016 -0700
@@ -84,9 +84,8 @@
public static final int MAX_RESTRICTED_EXPLEN = 64;
private static final boolean restrictExpLen =
- "true".equalsIgnoreCase(AccessController.doPrivileged(
- new GetPropertyAction(
- "sun.security.rsa.restrictRSAExponent", "true")));
+ "true".equalsIgnoreCase(GetPropertyAction.getProperty(
+ "sun.security.rsa.restrictRSAExponent", "true"));
// instance used for static translateKey();
private static final RSAKeyFactory INSTANCE = new RSAKeyFactory();
--- a/jdk/src/java.base/share/classes/sun/security/ssl/ClientKeyExchangeService.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/ClientKeyExchangeService.java Thu Apr 21 13:37:31 2016 -0700
@@ -50,10 +50,7 @@
providers = new HashMap<>();
static {
- final String key = "java.home";
- String path = AccessController.doPrivileged(
- new GetPropertyAction(key), null,
- new PropertyPermission(key, "read"));
+ String path = GetPropertyAction.getProperty("java.home");
ServiceLoader<ClientKeyExchangeService> sc =
AccessController.doPrivileged(
(PrivilegedAction<ServiceLoader<ClientKeyExchangeService>>)
--- a/jdk/src/java.base/share/classes/sun/security/ssl/Debug.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/Debug.java Thu Apr 21 13:37:31 2016 -0700
@@ -26,7 +26,6 @@
package sun.security.ssl;
import java.io.PrintStream;
-import java.security.AccessController;
import java.util.Locale;
import sun.security.util.HexDumpEncoder;
@@ -46,8 +45,7 @@
private static String args;
static {
- args = java.security.AccessController.doPrivileged(
- new GetPropertyAction("javax.net.debug", ""));
+ args = GetPropertyAction.getProperty("javax.net.debug", "");
args = args.toLowerCase(Locale.ENGLISH);
if (args.equals("help")) {
Help();
@@ -184,8 +182,7 @@
*/
static boolean getBooleanProperty(String propName, boolean defaultValue) {
// if set, require value of either true or false
- String b = AccessController.doPrivileged(
- new GetPropertyAction(propName));
+ String b = GetPropertyAction.getProperty(propName);
if (b == null) {
return defaultValue;
} else if (b.equalsIgnoreCase("false")) {
--- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java Thu Apr 21 13:37:31 2016 -0700
@@ -656,8 +656,7 @@
// the provider service. Instead, please handle the initialization
// exception in the caller's constructor.
static {
- String property = AccessController.doPrivileged(
- new GetPropertyAction(PROPERTY_NAME));
+ String property = GetPropertyAction.getProperty(PROPERTY_NAME);
if (property != null && property.length() != 0) {
// remove double quote marks from beginning/end of the property
if (property.length() > 1 && property.charAt(0) == '"' &&
--- a/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java Thu Apr 21 13:37:31 2016 -0700
@@ -119,8 +119,8 @@
private long statusRespTimeout;
static {
- String property = AccessController.doPrivileged(
- new GetPropertyAction("jdk.tls.ephemeralDHKeySize"));
+ String property =
+ GetPropertyAction.getProperty("jdk.tls.ephemeralDHKeySize");
if (property == null || property.length() == 0) {
useLegacyEphemeralDHKeys = false;
useSmartEphemeralDHKeys = false;
--- a/jdk/src/java.base/share/classes/sun/security/ssl/StatusResponseManager.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/StatusResponseManager.java Thu Apr 21 13:37:31 2016 -0700
@@ -73,8 +73,8 @@
DEFAULT_CACHE_LIFETIME));
cacheLifetime = life > 0 ? life : 0;
- String uriStr = AccessController.doPrivileged(
- new GetPropertyAction("jdk.tls.stapling.responderURI"));
+ String uriStr =
+ GetPropertyAction.getProperty("jdk.tls.stapling.responderURI");
URI tmpURI;
try {
tmpURI = ((uriStr != null && !uriStr.isEmpty()) ?
--- a/jdk/src/java.base/share/classes/sun/security/util/Debug.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/util/Debug.java Thu Apr 21 13:37:31 2016 -0700
@@ -29,6 +29,7 @@
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.Locale;
+import sun.security.action.GetPropertyAction;
/**
* A utility class for debuging.
@@ -42,13 +43,10 @@
private static String args;
static {
- args = java.security.AccessController.doPrivileged
- (new sun.security.action.GetPropertyAction
- ("java.security.debug"));
+ args = GetPropertyAction.getProperty("java.security.debug");
- String args2 = java.security.AccessController.doPrivileged
- (new sun.security.action.GetPropertyAction
- ("java.security.auth.debug"));
+ String args2 =
+ GetPropertyAction.getProperty("java.security.auth.debug");
if (args == null) {
args = args2;
--- a/jdk/src/java.base/share/classes/sun/util/calendar/LocalGregorianCalendar.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/util/calendar/LocalGregorianCalendar.java Thu Apr 21 13:37:31 2016 -0700
@@ -27,6 +27,7 @@
import java.security.AccessController;
import java.util.TimeZone;
+import sun.security.action.GetPropertyAction;
/**
*
@@ -142,8 +143,8 @@
}
// Append an era to the predefined eras if it's given by the property.
- String prop = AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("jdk.calendar.japanese.supplemental.era"));
+ String prop = GetPropertyAction
+ .getProperty("jdk.calendar.japanese.supplemental.era");
if (prop != null) {
Era era = parseEraEntry(prop);
if (era != null) {
--- a/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfoFile.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfoFile.java Thu Apr 21 13:37:31 2016 -0700
@@ -245,11 +245,12 @@
};
static {
- String oldmapping = AccessController.doPrivileged(
- new GetPropertyAction("sun.timezone.ids.oldmapping", "false")).toLowerCase(Locale.ROOT);
+ String oldmapping = GetPropertyAction
+ .getProperty("sun.timezone.ids.oldmapping", "false")
+ .toLowerCase(Locale.ROOT);
USE_OLDMAPPING = (oldmapping.equals("yes") || oldmapping.equals("true"));
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ public Void run() {
try {
String libDir = System.getProperty("java.home") + File.separator + "lib";
try (DataInputStream dis = new DataInputStream(
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java Thu Apr 21 13:37:31 2016 -0700
@@ -25,7 +25,6 @@
package sun.util.locale.provider;
-import java.security.AccessController;
import java.text.spi.BreakIteratorProvider;
import java.text.spi.CollatorProvider;
import java.text.spi.DateFormatProvider;
@@ -47,6 +46,7 @@
import java.util.spi.LocaleNameProvider;
import java.util.spi.LocaleServiceProvider;
import java.util.spi.TimeZoneNameProvider;
+import sun.security.action.GetPropertyAction;
import sun.util.spi.CalendarProvider;
/**
@@ -116,8 +116,7 @@
adapterCache = new ConcurrentHashMap<>();
static {
- String order = AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("java.locale.providers"));
+ String order = GetPropertyAction.getProperty("java.locale.providers");
List<Type> typeList = new ArrayList<>();
// Check user specified adapter preference
--- a/jdk/src/java.base/share/native/include/jvm.h Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/native/include/jvm.h Thu Apr 21 13:37:31 2016 -0700
@@ -179,7 +179,6 @@
*/
enum {
JVM_STACKWALK_FILL_CLASS_REFS_ONLY = 0x2,
- JVM_STACKWALK_FILTER_FILL_IN_STACK_TRACE = 0x10,
JVM_STACKWALK_SHOW_HIDDEN_FRAMES = 0x20,
JVM_STACKWALK_FILL_LIVE_STACK_FRAMES = 0x100
};
@@ -187,23 +186,15 @@
JNIEXPORT jobject JNICALL
JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mode,
jint skip_frames, jint frame_count, jint start_index,
- jobjectArray classes,
jobjectArray frames);
JNIEXPORT jint JNICALL
JVM_MoreStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jlong anchor,
jint frame_count, jint start_index,
- jobjectArray classes,
jobjectArray frames);
JNIEXPORT void JNICALL
-JVM_FillStackFrames(JNIEnv* env, jclass cls,
- jint start_index,
- jobjectArray stackFrames,
- jint from_index, jint toIndex);
-
-JNIEXPORT void JNICALL
-JVM_SetMethodInfo(JNIEnv* env, jobject frame);
+JVM_ToStackTraceElement(JNIEnv* env, jobject frame, jobject stackElement);
JNIEXPORT jobjectArray JNICALL
JVM_GetVmArguments(JNIEnv *env);
--- a/jdk/src/java.base/share/native/launcher/defines.h Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/native/launcher/defines.h Thu Apr 21 13:37:31 2016 -0700
@@ -45,7 +45,11 @@
#ifdef JAVA_ARGS
#define HAS_JAVA_ARGS JNI_TRUE
-static const char* const_progname = "java";
+#ifdef PROGNAME
+static const char* const_progname = PROGNAME;
+#else
+static char* const_progname = NULL;
+#endif
static const char* const_jargs[] = JAVA_ARGS;
/*
* ApplicationHome is prepended to each of these entries; the resulting
@@ -59,11 +63,7 @@
#endif /* APP_CLASSPATH */
#else /* !JAVA_ARGS */
#define HAS_JAVA_ARGS JNI_FALSE
-#ifdef PROGNAME
-static const char* const_progname = PROGNAME;
-#else
-static char* const_progname = NULL;
-#endif
+static const char* const_progname = "java";
static const char** const_jargs = NULL;
static const char* const_appclasspath[] = { NULL };
#endif /* JAVA_ARGS */
--- a/jdk/src/java.base/share/native/libjava/StackFrameInfo.c Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/native/libjava/StackFrameInfo.c Thu Apr 21 13:37:31 2016 -0700
@@ -38,22 +38,10 @@
/*
* Class: java_lang_StackFrameInfo
- * Method: fillInStackFrames
- * Signature: (I[Ljava/lang/Object;[Ljava/lang/Object;II)V
+ * Method: toStackTraceElement0
+ * Signature: (Ljava/lang/StackTraceElement;)V
*/
-JNIEXPORT void JNICALL Java_java_lang_StackFrameInfo_fillInStackFrames
- (JNIEnv *env, jclass dummy, jint startIndex,
- jobjectArray stackFrames, jint fromIndex, jint toIndex) {
- JVM_FillStackFrames(env, dummy, startIndex,
- stackFrames, fromIndex, toIndex);
+JNIEXPORT void JNICALL Java_java_lang_StackFrameInfo_toStackTraceElement0
+ (JNIEnv *env, jobject stackframeinfo, jobject stacktraceinfo) {
+ JVM_ToStackTraceElement(env, stackframeinfo, stacktraceinfo);
}
-
-/*
- * Class: java_lang_StackFrameInfo
- * Method: setMethodInfo
- * Signature: (Ljava/lang/Class;)V
- */
-JNIEXPORT void JNICALL Java_java_lang_StackFrameInfo_setMethodInfo
- (JNIEnv *env, jobject stackframeinfo) {
- JVM_SetMethodInfo(env, stackframeinfo);
-}
--- a/jdk/src/java.base/share/native/libjava/StackStreamFactory.c Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/share/native/libjava/StackStreamFactory.c Thu Apr 21 13:37:31 2016 -0700
@@ -45,7 +45,6 @@
(JNIEnv *env, jclass dummy)
{
return JVM_STACKWALK_FILL_CLASS_REFS_ONLY == java_lang_StackStreamFactory_FILL_CLASS_REFS_ONLY &&
- JVM_STACKWALK_FILTER_FILL_IN_STACK_TRACE == java_lang_StackStreamFactory_FILTER_FILL_IN_STACKTRACE &&
JVM_STACKWALK_SHOW_HIDDEN_FRAMES == java_lang_StackStreamFactory_SHOW_HIDDEN_FRAMES &&
JVM_STACKWALK_FILL_LIVE_STACK_FRAMES == java_lang_StackStreamFactory_FILL_LIVE_STACK_FRAMES;
}
@@ -53,26 +52,26 @@
/*
* Class: java_lang_StackStreamFactory_AbstractStackWalker
* Method: callStackWalk
- * Signature: (JIII[Ljava/lang/Class;[Ljava/lang/StackWalker/StackFrame;)Ljava/lang/Object;
+ * Signature: (JIII[Ljava/lang/Object;)Ljava/lang/Object;
*/
JNIEXPORT jobject JNICALL Java_java_lang_StackStreamFactory_00024AbstractStackWalker_callStackWalk
(JNIEnv *env, jobject stackstream, jlong mode, jint skipFrames, jint batchSize, jint startIndex,
- jobjectArray classes, jobjectArray frames)
+ jobjectArray frames)
{
return JVM_CallStackWalk(env, stackstream, mode, skipFrames, batchSize,
- startIndex, classes, frames);
+ startIndex, frames);
}
/*
* Class: java_lang_StackStreamFactory_AbstractStackWalker
* Method: fetchStackFrames
- * Signature: (JJII[Ljava/lang/Class;[Ljava/lang/StackWalker/StackFrame;)I
+ * Signature: (JJII[Ljava/lang/Object;)I
*/
JNIEXPORT jint JNICALL Java_java_lang_StackStreamFactory_00024AbstractStackWalker_fetchStackFrames
(JNIEnv *env, jobject stackstream, jlong mode, jlong anchor,
jint batchSize, jint startIndex,
- jobjectArray classes, jobjectArray frames)
+ jobjectArray frames)
{
return JVM_MoreStackWalk(env, stackstream, mode, anchor, batchSize,
- startIndex, classes, frames);
+ startIndex, frames);
}
--- a/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystem.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystem.java Thu Apr 21 13:37:31 2016 -0700
@@ -28,7 +28,6 @@
import java.nio.file.*;
import java.io.IOException;
import java.util.*;
-import java.security.AccessController;
import sun.security.action.GetPropertyAction;
import static sun.nio.fs.SolarisNativeDispatcher.*;
@@ -43,8 +42,7 @@
super(provider, dir);
// check os.version
- String osversion = AccessController
- .doPrivileged(new GetPropertyAction("os.version"));
+ String osversion = GetPropertyAction.getProperty("os.version");
String[] vers = Util.split(osversion, '.');
assert vers.length >= 2;
int majorVersion = Integer.parseInt(vers[0]);
--- a/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java Thu Apr 21 13:37:31 2016 -0700
@@ -29,7 +29,6 @@
import java.nio.file.attribute.*;
import java.nio.file.spi.FileTypeDetector;
import java.io.IOException;
-import java.security.AccessController;
import sun.security.action.GetPropertyAction;
/**
@@ -85,8 +84,8 @@
@Override
FileTypeDetector getFileTypeDetector() {
- Path userMimeTypes = Paths.get(AccessController.doPrivileged(
- new GetPropertyAction("user.home")), ".mime.types");
+ Path userMimeTypes = Paths.get(
+ GetPropertyAction.getProperty("user.home"), ".mime.types");
Path etcMimeTypes = Paths.get("/etc/mime.types");
return chain(new GioFileTypeDetector(),
--- a/jdk/src/java.base/unix/classes/java/io/UnixFileSystem.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/unix/classes/java/io/UnixFileSystem.java Thu Apr 21 13:37:31 2016 -0700
@@ -25,7 +25,7 @@
package java.io;
-import java.security.AccessController;
+import java.util.Properties;
import sun.security.action.GetPropertyAction;
@@ -36,12 +36,10 @@
private final String javaHome;
public UnixFileSystem() {
- slash = AccessController.doPrivileged(
- new GetPropertyAction("file.separator")).charAt(0);
- colon = AccessController.doPrivileged(
- new GetPropertyAction("path.separator")).charAt(0);
- javaHome = AccessController.doPrivileged(
- new GetPropertyAction("java.home"));
+ Properties props = GetPropertyAction.getProperties();
+ slash = props.getProperty("file.separator").charAt(0);
+ colon = props.getProperty("path.separator").charAt(0);
+ javaHome = props.getProperty("java.home");
}
--- a/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java Thu Apr 21 13:37:31 2016 -0700
@@ -46,8 +46,10 @@
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
+import java.util.Properties;
import jdk.internal.misc.JavaIOFileDescriptorAccess;
import jdk.internal.misc.SharedSecrets;
+import sun.security.action.GetPropertyAction;
/**
* java.lang.Process subclass in the UNIX environment.
@@ -123,11 +125,9 @@
}
String helperPath() {
- return AccessController.doPrivileged(
- (PrivilegedAction<String>) () ->
- helperPath(System.getProperty("java.home"),
- System.getProperty("os.arch"))
- );
+ Properties props = GetPropertyAction.getProperties();
+ return helperPath(props.getProperty("java.home"),
+ props.getProperty("os.arch"));
}
LaunchMechanism launchMechanism() {
@@ -159,9 +159,7 @@
}
static Platform get() {
- String osName = AccessController.doPrivileged(
- (PrivilegedAction<String>) () -> System.getProperty("os.name")
- );
+ String osName = GetPropertyAction.getProperty("os.name");
if (osName.equals("Linux")) { return LINUX; }
if (osName.contains("OS X")) { return BSD; }
--- a/jdk/src/java.base/unix/classes/java/net/DefaultDatagramSocketImplFactory.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/unix/classes/java/net/DefaultDatagramSocketImplFactory.java Thu Apr 21 13:37:31 2016 -0700
@@ -24,7 +24,7 @@
*/
package java.net;
-import java.security.AccessController;
+import sun.security.action.GetPropertyAction;
/**
* This class defines a factory for creating DatagramSocketImpls. It defaults
@@ -40,8 +40,7 @@
static {
String prefix = null;
try {
- prefix = AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("impl.prefix", null));
+ prefix = GetPropertyAction.getProperty("impl.prefix", null);
if (prefix != null)
prefixImplClass = Class.forName("java.net."+prefix+"DatagramSocketImpl");
} catch (Exception e) {
--- a/jdk/src/java.base/unix/classes/sun/net/sdp/SdpProvider.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/unix/classes/sun/net/sdp/SdpProvider.java Thu Apr 21 13:37:31 2016 -0700
@@ -34,7 +34,6 @@
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintStream;
-import java.security.AccessController;
import sun.net.sdp.SdpSupport;
import sun.security.action.GetPropertyAction;
@@ -57,8 +56,7 @@
public SdpProvider() {
// if this property is not defined then there is nothing to do.
- String file = AccessController.doPrivileged(
- new GetPropertyAction("com.sun.sdp.conf"));
+ String file = GetPropertyAction.getProperty("com.sun.sdp.conf");
if (file == null) {
this.enabled = false;
this.rules = null;
@@ -77,8 +75,7 @@
// check if debugging is enabled
PrintStream out = null;
- String logfile = AccessController.doPrivileged(
- new GetPropertyAction("com.sun.sdp.debug"));
+ String logfile = GetPropertyAction.getProperty("com.sun.sdp.debug");
if (logfile != null) {
out = System.out;
if (logfile.length() > 0) {
--- a/jdk/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java Thu Apr 21 13:37:31 2016 -0700
@@ -39,6 +39,7 @@
import sun.net.www.protocol.http.AuthenticationInfo;
import sun.net.www.protocol.http.AuthScheme;
import sun.net.www.protocol.http.HttpURLConnection;
+import sun.security.action.GetPropertyAction;
/**
* NTLMAuthentication:
@@ -73,12 +74,9 @@
NTLMAuthenticationCallback.getNTLMAuthenticationCallback();
private String hostname;
- private static String defaultDomain; /* Domain to use if not specified by user */
-
- static {
- defaultDomain = java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("http.auth.ntlm.domain", ""));
- };
+ /* Domain to use if not specified by user */
+ private static String defaultDomain =
+ GetPropertyAction.getProperty("http.auth.ntlm.domain", "");
public static boolean supportsTransparentAuth () {
return false;
@@ -143,8 +141,7 @@
password = pw.getPassword();
init0();
try {
- String version = java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("ntlm.version"));
+ String version = GetPropertyAction.getProperty("ntlm.version");
client = new Client(version, hostname, username, ntdomain, password);
} catch (NTLMException ne) {
try {
--- a/jdk/src/java.base/unix/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/unix/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java Thu Apr 21 13:37:31 2016 -0700
@@ -26,7 +26,6 @@
package sun.nio.ch;
import java.nio.channels.spi.AsynchronousChannelProvider;
-import java.security.AccessController;
import sun.security.action.GetPropertyAction;
/**
@@ -60,8 +59,7 @@
* Returns the default AsynchronousChannelProvider.
*/
public static AsynchronousChannelProvider create() {
- String osname = AccessController
- .doPrivileged(new GetPropertyAction("os.name"));
+ String osname = GetPropertyAction.getProperty("os.name");
if (osname.equals("SunOS"))
return createProvider("sun.nio.ch.SolarisAsynchronousChannelProvider");
if (osname.equals("Linux"))
--- a/jdk/src/java.base/unix/classes/sun/nio/ch/InheritedChannel.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/unix/classes/sun/nio/ch/InheritedChannel.java Thu Apr 21 13:37:31 2016 -0700
@@ -168,7 +168,7 @@
Class<?> paramTypes[] = { int.class };
Constructor<?> ctr = Reflect.lookupConstructor("java.io.FileDescriptor",
paramTypes);
- Object args[] = { new Integer(fdVal) };
+ Object args[] = { Integer.valueOf(fdVal) };
FileDescriptor fd = (FileDescriptor)Reflect.invoke(ctr, args);
--- a/jdk/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java Thu Apr 21 13:37:31 2016 -0700
@@ -31,7 +31,6 @@
import java.util.concurrent.*;
import java.io.IOException;
import java.io.FileDescriptor;
-import java.security.AccessController;
import sun.net.NetHooks;
import sun.security.action.GetPropertyAction;
@@ -47,8 +46,8 @@
private static final boolean disableSynchronousRead;
static {
- String propValue = AccessController.doPrivileged(
- new GetPropertyAction("sun.nio.ch.disableSynchronousRead", "false"));
+ String propValue = GetPropertyAction
+ .getProperty("sun.nio.ch.disableSynchronousRead", "false");
disableSynchronousRead = (propValue.length() == 0) ?
true : Boolean.valueOf(propValue);
}
--- a/jdk/src/java.base/unix/classes/sun/nio/fs/DefaultFileSystemProvider.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/unix/classes/sun/nio/fs/DefaultFileSystemProvider.java Thu Apr 21 13:37:31 2016 -0700
@@ -26,7 +26,6 @@
package sun.nio.fs;
import java.nio.file.spi.FileSystemProvider;
-import java.security.AccessController;
import sun.security.action.GetPropertyAction;
/**
@@ -55,8 +54,7 @@
* Returns the default FileSystemProvider.
*/
public static FileSystemProvider create() {
- String osname = AccessController
- .doPrivileged(new GetPropertyAction("os.name"));
+ String osname = GetPropertyAction.getProperty("os.name");
if (osname.equals("SunOS"))
return createProvider("sun.nio.fs.SolarisFileSystemProvider");
if (osname.equals("Linux"))
--- a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java Thu Apr 21 13:37:31 2016 -0700
@@ -31,7 +31,6 @@
import java.io.IOException;
import java.util.*;
import java.util.regex.Pattern;
-import java.security.AccessController;
import sun.security.action.GetPropertyAction;
/**
@@ -57,8 +56,8 @@
// if process-wide chdir is allowed or default directory is not the
// process working directory then paths must be resolved against the
// default directory.
- String propValue = AccessController.doPrivileged(
- new GetPropertyAction("sun.nio.fs.chdirAllowed", "false"));
+ String propValue = GetPropertyAction
+ .getProperty("sun.nio.fs.chdirAllowed", "false");
boolean chdirAllowed = (propValue.length() == 0) ?
true : Boolean.valueOf(propValue);
if (chdirAllowed) {
--- a/jdk/src/java.base/windows/classes/java/io/WinNTFileSystem.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/windows/classes/java/io/WinNTFileSystem.java Thu Apr 21 13:37:31 2016 -0700
@@ -25,8 +25,8 @@
package java.io;
-import java.security.AccessController;
import java.util.Locale;
+import java.util.Properties;
import sun.security.action.GetPropertyAction;
/**
@@ -42,10 +42,9 @@
private final char semicolon;
public WinNTFileSystem() {
- slash = AccessController.doPrivileged(
- new GetPropertyAction("file.separator")).charAt(0);
- semicolon = AccessController.doPrivileged(
- new GetPropertyAction("path.separator")).charAt(0);
+ Properties props = GetPropertyAction.getProperties();
+ slash = props.getProperty("file.separator").charAt(0);
+ semicolon = props.getProperty("path.separator").charAt(0);
altSlash = (this.slash == '\\') ? '/' : '\\';
}
--- a/jdk/src/java.base/windows/classes/java/net/DefaultDatagramSocketImplFactory.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/windows/classes/java/net/DefaultDatagramSocketImplFactory.java Thu Apr 21 13:37:31 2016 -0700
@@ -24,8 +24,7 @@
*/
package java.net;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
+import java.util.Properties;
import sun.security.action.GetPropertyAction;
/**
@@ -57,12 +56,11 @@
static {
Class<?> prefixImplClassLocal = null;
+ Properties props = GetPropertyAction.getProperties();
preferIPv4Stack = Boolean.parseBoolean(
- AccessController.doPrivileged(
- new GetPropertyAction("java.net.preferIPv4Stack")));
+ props.getProperty("java.net.preferIPv4Stack"));
- String exclBindProp = AccessController.doPrivileged(
- new GetPropertyAction("sun.net.useExclusiveBind", ""));
+ String exclBindProp = props.getProperty("sun.net.useExclusiveBind", "");
exclusiveBind = (exclBindProp.isEmpty())
? true
: Boolean.parseBoolean(exclBindProp);
@@ -70,8 +68,7 @@
// impl.prefix
String prefix = null;
try {
- prefix = AccessController.doPrivileged(
- new GetPropertyAction("impl.prefix", null));
+ prefix = props.getProperty("impl.prefix");
if (prefix != null)
prefixImplClassLocal = Class.forName("java.net."+prefix+"DatagramSocketImpl");
} catch (Exception e) {
--- a/jdk/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java Thu Apr 21 13:37:31 2016 -0700
@@ -220,7 +220,7 @@
case IP_TOS :
case SO_RCVBUF :
case SO_SNDBUF :
- returnValue = new Integer(value);
+ returnValue = Integer.valueOf(value);
break;
default: /* shouldn't get here */
throw new SocketException("Option not supported");
--- a/jdk/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java Thu Apr 21 13:37:31 2016 -0700
@@ -34,6 +34,7 @@
import sun.net.www.protocol.http.AuthenticationInfo;
import sun.net.www.protocol.http.AuthScheme;
import sun.net.www.protocol.http.HttpURLConnection;
+import sun.security.action.GetPropertyAction;
/**
* NTLMAuthentication:
@@ -52,9 +53,8 @@
private static String defaultDomain; /* Domain to use if not specified by user */
static {
- defaultDomain = java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("http.auth.ntlm.domain",
- "domain"));
+ defaultDomain = GetPropertyAction.getProperty("http.auth.ntlm.domain",
+ "domain");
};
private void init0() {
--- a/jdk/src/java.base/windows/classes/sun/nio/ch/FileDispatcherImpl.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/windows/classes/sun/nio/ch/FileDispatcherImpl.java Thu Apr 21 13:37:31 2016 -0700
@@ -27,9 +27,9 @@
import java.io.FileDescriptor;
import java.io.IOException;
-import java.security.PrivilegedAction;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.misc.JavaIOFileDescriptorAccess;
+import sun.security.action.GetPropertyAction;
class FileDispatcherImpl extends FileDispatcher {
@@ -119,13 +119,8 @@
}
static boolean isFastFileTransferRequested() {
- String fileTransferProp = java.security.AccessController.doPrivileged(
- new PrivilegedAction<String>() {
- @Override
- public String run() {
- return System.getProperty("jdk.nio.enableFastFileTransfer");
- }
- });
+ String fileTransferProp = GetPropertyAction
+ .getProperty("jdk.nio.enableFastFileTransfer");
boolean enable;
if ("".equals(fileTransferProp)) {
enable = true;
--- a/jdk/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java Thu Apr 21 13:37:31 2016 -0700
@@ -87,13 +87,13 @@
private static final class FdMap extends HashMap<Integer, MapEntry> {
static final long serialVersionUID = 0L;
private MapEntry get(int desc) {
- return get(new Integer(desc));
+ return get(Integer.valueOf(desc));
}
private MapEntry put(SelectionKeyImpl ski) {
- return put(new Integer(ski.channel.getFDVal()), new MapEntry(ski));
+ return put(Integer.valueOf(ski.channel.getFDVal()), new MapEntry(ski));
}
private MapEntry remove(SelectionKeyImpl ski) {
- Integer fd = new Integer(ski.channel.getFDVal());
+ Integer fd = Integer.valueOf(ski.channel.getFDVal());
MapEntry x = get(fd);
if ((x != null) && (x.ski.channel == ski.channel))
return remove(fd);
--- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java Thu Apr 21 13:37:31 2016 -0700
@@ -27,7 +27,6 @@
import java.nio.file.attribute.*;
import java.util.concurrent.TimeUnit;
-import java.security.AccessController;
import jdk.internal.misc.Unsafe;
import sun.security.action.GetPropertyAction;
@@ -115,8 +114,8 @@
// indicates if accurate metadata is required (interesting on NTFS only)
private static final boolean ensureAccurateMetadata;
static {
- String propValue = AccessController.doPrivileged(
- new GetPropertyAction("sun.nio.fs.ensureAccurateMetadata", "false"));
+ String propValue = GetPropertyAction
+ .getProperty("sun.nio.fs.ensureAccurateMetadata", "false");
ensureAccurateMetadata = (propValue.length() == 0) ?
true : Boolean.valueOf(propValue);
}
--- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaFileSystemModel.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaFileSystemModel.java Thu Apr 21 13:37:31 2016 -0700
@@ -35,7 +35,6 @@
import javax.swing.filechooser.FileSystemView;
import javax.swing.table.AbstractTableModel;
-import sun.misc.ManagedLocalsThread;
/**
* NavServices-like implementation of a file Table
*
@@ -393,7 +392,7 @@
this.currentDirectory = currentDirectory;
this.fid = fid;
String name = "Aqua L&F File Loading Thread";
- this.loadThread = new ManagedLocalsThread(this, name);
+ this.loadThread = new Thread(null, this, name, 0, false);
this.loadThread.start();
}
--- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameDockIconUI.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameDockIconUI.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, 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,28 +40,28 @@
* From MacDockIconUI
*
* A JRSUI L&F implementation of JInternalFrame.JDesktopIcon
- * @author
- * @version
*/
-public class AquaInternalFrameDockIconUI extends DesktopIconUI implements MouseListener, MouseMotionListener, ComponentListener {
- private static final String CACHED_FRAME_ICON_KEY = "apple.laf.internal.frameIcon";
+public final class AquaInternalFrameDockIconUI extends DesktopIconUI
+ implements MouseListener, MouseMotionListener {
- protected JInternalFrame.JDesktopIcon fDesktopIcon;
- protected JInternalFrame fFrame;
- protected ScaledImageLabel fIconPane;
- protected DockLabel fDockLabel;
- protected boolean fTrackingIcon = false;
+ private JInternalFrame.JDesktopIcon fDesktopIcon;
+ private JInternalFrame fFrame;
+ private ScaledImageLabel fIconPane;
+ private DockLabel fDockLabel;
+ private boolean fTrackingIcon;
public static ComponentUI createUI(final JComponent c) {
return new AquaInternalFrameDockIconUI();
}
+ @Override
public void installUI(final JComponent c) {
fDesktopIcon = (JInternalFrame.JDesktopIcon)c;
installComponents();
installListeners();
}
+ @Override
public void uninstallUI(final JComponent c) {
uninstallComponents();
uninstallListeners();
@@ -69,55 +69,54 @@
fFrame = null;
}
- protected void installComponents() {
+ private void installComponents() {
fFrame = fDesktopIcon.getInternalFrame();
fIconPane = new ScaledImageLabel();
fDesktopIcon.setLayout(new BorderLayout());
fDesktopIcon.add(fIconPane, BorderLayout.CENTER);
}
- protected void uninstallComponents() {
+ private void uninstallComponents() {
fDesktopIcon.setLayout(null);
fDesktopIcon.remove(fIconPane);
}
- protected void installListeners() {
+ private void installListeners() {
fDesktopIcon.addMouseListener(this);
fDesktopIcon.addMouseMotionListener(this);
- fFrame.addComponentListener(this);
}
- protected void uninstallListeners() {
- fFrame.removeComponentListener(this);
+ private void uninstallListeners() {
fDesktopIcon.removeMouseMotionListener(this);
fDesktopIcon.removeMouseListener(this);
}
+ @Override
public Dimension getMinimumSize(final JComponent c) {
return new Dimension(32, 32);
}
+ @Override
public Dimension getMaximumSize(final JComponent c) {
return new Dimension(128, 128);
}
+ @Override
public Dimension getPreferredSize(final JComponent c) {
return new Dimension(64, 64); //$ Dock preferred size
}
- public Insets getInsets(final JComponent c) {
- return new Insets(0, 0, 0, 0);
- }
-
void updateIcon() {
fIconPane.updateIcon();
}
+ @Override
public void mousePressed(final MouseEvent e) {
fTrackingIcon = fIconPane.mouseInIcon(e);
if (fTrackingIcon) fIconPane.repaint();
}
+ @Override
public void mouseReleased(final MouseEvent e) {// only when it's actually in the image
if (fFrame.isIconifiable() && fFrame.isIcon()) {
if (fTrackingIcon) {
@@ -137,6 +136,7 @@
if (fDockLabel != null && !fIconPane.getBounds().contains(e.getX(), e.getY())) fDockLabel.hide();
}
+ @Override
public void mouseEntered(final MouseEvent e) {
if ((e.getModifiers() & InputEvent.BUTTON1_MASK) != 0) return;
String title = fFrame.getTitle();
@@ -145,41 +145,27 @@
fDockLabel.show(fDesktopIcon);
}
+ @Override
public void mouseExited(final MouseEvent e) {
if (fDockLabel != null && (e.getModifiers() & InputEvent.BUTTON1_MASK) == 0) fDockLabel.hide();
}
+ @Override
public void mouseClicked(final MouseEvent e) { }
+ @Override
public void mouseDragged(final MouseEvent e) { }
+ @Override
public void mouseMoved(final MouseEvent e) { }
- public void componentHidden(final ComponentEvent e) { }
-
- public void componentMoved(final ComponentEvent e) { }
-
- public void componentResized(final ComponentEvent e) {
- fFrame.putClientProperty(CACHED_FRAME_ICON_KEY, null);
- }
-
- public void componentShown(final ComponentEvent e) {
- fFrame.putClientProperty(CACHED_FRAME_ICON_KEY, null);
- }
-
@SuppressWarnings("serial") // Superclass is not serializable across versions
- class ScaledImageLabel extends JLabel {
+ private final class ScaledImageLabel extends JLabel {
ScaledImageLabel() {
super(null, null, CENTER);
}
void updateIcon() {
- final Object priorIcon = fFrame.getClientProperty(CACHED_FRAME_ICON_KEY);
- if (priorIcon instanceof ImageIcon) {
- setIcon((ImageIcon)priorIcon);
- return;
- }
-
int width = fFrame.getWidth();
int height = fFrame.getHeight();
@@ -196,11 +182,10 @@
final float scale = (float)fDesktopIcon.getWidth() / (float)Math.max(width, height) * 0.89f;
// Sending in -1 for width xor height causes it to maintain aspect ratio
- final ImageIcon icon = new ImageIcon(fImage.getScaledInstance((int)(width * scale), -1, Image.SCALE_SMOOTH));
- fFrame.putClientProperty(CACHED_FRAME_ICON_KEY, icon);
- setIcon(icon);
+ setIcon(new ImageIcon(fImage.getScaledInstance((int)(width * scale), -1, Image.SCALE_SMOOTH)));
}
+ @Override
public void paint(final Graphics g) {
if (getIcon() == null) updateIcon();
@@ -222,13 +207,14 @@
return getBounds().contains(e.getX(), e.getY());
}
+ @Override
public Dimension getPreferredSize() {
return new Dimension(64, 64); //$ Dock preferred size
}
}
@SuppressWarnings("serial") // Superclass is not serializable across versions
- class DockLabel extends JLabel {
+ private static final class DockLabel extends JLabel {
static final int NUB_HEIGHT = 7;
static final int ROUND_ADDITIONAL_HEIGHT = 8;
static final int ROUND_ADDITIONAL_WIDTH = 12;
@@ -243,6 +229,7 @@
setSize(SwingUtilities.computeStringWidth(metrics, getText()) + ROUND_ADDITIONAL_WIDTH * 2, metrics.getAscent() + NUB_HEIGHT + ROUND_ADDITIONAL_HEIGHT);
}
+ @Override
public void paint(final Graphics g) {
final int width = getWidth();
final int height = getHeight();
@@ -303,6 +290,7 @@
}
}
+ @Override
@Deprecated
public void hide() {
final Container parent = getParent();
--- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java Thu Apr 21 13:37:31 2016 -0700
@@ -2183,50 +2183,21 @@
}
protected int preferredTabAreaHeight(final int tabPlacement, final int width) {
- final FontMetrics metrics = getFontMetrics();
final int tabCount = tabPane.getTabCount();
int total = 0;
if (tabCount > 0) {
- int rows = 1;
- int x = 0;
-
final int maxTabHeight = calculateMaxTabHeight(tabPlacement);
-
- for (int i = 0; i < tabCount; i++) {
- final int tabWidth = calculateTabWidth(tabPlacement, i, metrics);
-
- if (x != 0 && x + tabWidth > width) {
- rows++;
- x = 0;
- }
- x += tabWidth;
- }
- total = calculateTabAreaHeight(tabPlacement, rows, maxTabHeight);
+ total = calculateTabAreaHeight(tabPlacement, 1, maxTabHeight);
}
return total;
}
protected int preferredTabAreaWidth(final int tabPlacement, final int height) {
- final FontMetrics metrics = getFontMetrics();
final int tabCount = tabPane.getTabCount();
int total = 0;
if (tabCount > 0) {
- int columns = 1;
- int y = 0;
- final int fontHeight = metrics.getHeight();
-
maxTabWidth = calculateMaxTabWidth(tabPlacement);
-
- for (int i = 0; i < tabCount; i++) {
- final int tabHeight = calculateTabHeight(tabPlacement, i, fontHeight);
-
- if (y != 0 && y + tabHeight > height) {
- columns++;
- y = 0;
- }
- y += tabHeight;
- }
- total = calculateTabAreaWidth(tabPlacement, columns, maxTabWidth);
+ total = calculateTabAreaWidth(tabPlacement, 1, maxTabWidth);
}
return total;
}
--- a/jdk/src/java.desktop/macosx/classes/sun/font/CFontManager.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/macosx/classes/sun/font/CFontManager.java Thu Apr 21 13:37:31 2016 -0700
@@ -42,7 +42,6 @@
import sun.awt.HeadlessToolkit;
import sun.awt.util.ThreadGroupUtils;
import sun.lwawt.macosx.*;
-import sun.misc.ManagedLocalsThread;
public final class CFontManager extends SunFontManager {
private static Hashtable<String, Font2D> genericFonts = new Hashtable<String, Font2D>();
--- a/jdk/src/java.desktop/macosx/classes/sun/java2d/IntegerNIORaster.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/macosx/classes/sun/java2d/IntegerNIORaster.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, 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 @@
") cannot be <= 0");
}
// This is cribbed from java.awt.image.Raster.
- DataBuffer db = new DataBufferNIOInt(w * h);
+ DataBufferNIOInt db = new DataBufferNIOInt(w * h);
if (location == null) {
location = new Point(0, 0);
}
@@ -48,13 +48,11 @@
return new IntegerNIORaster(sppsm, db, location);
}
- public IntegerNIORaster(SampleModel sampleModel, DataBuffer dataBuffer, Point origin) {
+ public IntegerNIORaster(SampleModel sampleModel, DataBufferNIOInt dataBuffer, Point origin) {
// This is all cribbed from sun.awt.image.IntegerInterleavedRaster & sun.awt.image.IntegerComponentRaster
super(sampleModel, dataBuffer, new Rectangle(origin.x, origin.y, sampleModel.getWidth(), sampleModel.getHeight()), origin, null);
- if (!(dataBuffer instanceof DataBufferNIOInt)) {
- throw new RasterFormatException("IntegerNIORasters must have DataBufferNIOInt DataBuffers");
- }
- this.data = ((DataBufferNIOInt)dataBuffer).getBuffer();
+
+ this.data = dataBuffer.getBuffer();
}
public WritableRaster createCompatibleWritableRaster() {
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java Thu Apr 21 13:37:31 2016 -0700
@@ -35,7 +35,6 @@
import java.util.*;
import sun.awt.*;
-import sun.misc.ManagedLocalsThread;
import sun.print.*;
import sun.awt.util.ThreadGroupUtils;
@@ -77,13 +76,14 @@
shutdown();
waitForRunState(STATE_CLEANUP);
};
- Thread shutdown = new ManagedLocalsThread(
- ThreadGroupUtils.getRootThreadGroup(), shutdownRunnable);
+ Thread shutdown = new Thread(
+ ThreadGroupUtils.getRootThreadGroup(), shutdownRunnable,
+ "AWT-Shutdown", 0, false);
shutdown.setContextClassLoader(null);
Runtime.getRuntime().addShutdownHook(shutdown);
String name = "AWT-LW";
- Thread toolkitThread = new ManagedLocalsThread(
- ThreadGroupUtils.getRootThreadGroup(), this, name);
+ Thread toolkitThread = new Thread(
+ ThreadGroupUtils.getRootThreadGroup(), this, name, 0, false);
toolkitThread.setDaemon(true);
toolkitThread.setPriority(Thread.NORM_PRIORITY + 1);
toolkitThread.start();
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java Thu Apr 21 13:37:31 2016 -0700
@@ -44,7 +44,6 @@
import sun.lwawt.LWComponentPeer;
import sun.lwawt.LWWindowPeer;
import sun.lwawt.PlatformWindow;
-import sun.misc.ManagedLocalsThread;
public final class CDragSourceContextPeer extends SunDragSourceContextPeer {
@@ -181,7 +180,7 @@
}
}
};
- new ManagedLocalsThread(dragRunnable).start();
+ new Thread(null, dragRunnable, "Drag", 0, false).start();
} catch (Exception e) {
final long nativeDragSource = getNativeContext();
setNativeContext(0);
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFileDialog.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFileDialog.java Thu Apr 21 13:37:31 2016 -0700
@@ -37,7 +37,6 @@
import sun.awt.CausedFocusEvent.Cause;
import sun.awt.AWTAccessor;
import sun.java2d.pipe.Region;
-import sun.misc.ManagedLocalsThread;
import sun.security.action.GetBooleanAction;
class CFileDialog implements FileDialogPeer {
@@ -120,7 +119,7 @@
if (visible) {
// Java2 Dialog class requires peer to run code in a separate thread
// and handles keeping the call modal
- new ManagedLocalsThread(new Task()).start();
+ new Thread(null, new Task(), "FileDialog", 0, false).start();
}
// We hide ourself before "show" returns - setVisible(false)
// doesn't apply
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterDialogPeer.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterDialogPeer.java Thu Apr 21 13:37:31 2016 -0700
@@ -29,7 +29,6 @@
import java.awt.dnd.*;
import sun.lwawt.*;
-import sun.misc.ManagedLocalsThread;
public class CPrinterDialogPeer extends LWWindowPeer {
static {
@@ -59,7 +58,7 @@
printerDialog.setRetVal(printerDialog.showDialog());
printerDialog.setVisible(false);
};
- new ManagedLocalsThread(task).start();
+ new Thread(null, task, "PrintDialog", 0, false).start();
}
}
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java Thu Apr 21 13:37:31 2016 -0700
@@ -36,6 +36,7 @@
import javax.print.*;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.HashPrintRequestAttributeSet;
+import javax.print.attribute.standard.Copies;
import javax.print.attribute.standard.Media;
import javax.print.attribute.standard.MediaPrintableArea;
import javax.print.attribute.standard.MediaSize;
@@ -43,7 +44,6 @@
import javax.print.attribute.standard.PageRanges;
import sun.java2d.*;
-import sun.misc.ManagedLocalsThread;
import sun.print.*;
public final class CPrinterJob extends RasterPrinterJob {
@@ -194,10 +194,37 @@
// setPageRange will set firstPage and lastPage as called in getFirstPage
// and getLastPage
setPageRange(range[0][0] - 1, range[0][1] - 1);
+ } else {
+ // if rangeSelect is SunPageSelection.ALL
+ // then setPageRange appropriately
+ setPageRange(-1, -1);
}
}
}
+ private void setPageRangeAttribute(int from, int to, boolean isRangeSet) {
+ if (attributes != null) {
+ // since native Print use zero-based page indices,
+ // we need to store in 1-based format in attributes set
+ // but setPageRange again uses zero-based indices so it should be
+ // 1 less than pageRanges attribute
+ if (isRangeSet) {
+ attributes.add(new PageRanges(from+1, to+1));
+ attributes.add(SunPageSelection.RANGE);
+ setPageRange(from, to);
+ } else {
+ attributes.add(SunPageSelection.ALL);
+ }
+ }
+ }
+
+ private void setCopiesAttribute(int copies) {
+ if (attributes != null) {
+ attributes.add(new Copies(copies));
+ super.setCopies(copies);
+ }
+ }
+
volatile boolean onEventThread;
@Override
@@ -691,9 +718,15 @@
if (pageFormat != null) {
Printable printable = pageable.getPrintable(pageIndex);
if (printable != null) {
- BufferedImage bimg = new BufferedImage((int)Math.round(pageFormat.getWidth()), (int)Math.round(pageFormat.getHeight()), BufferedImage.TYPE_INT_ARGB_PRE);
- PeekGraphics peekGraphics = createPeekGraphics(bimg.createGraphics(), printerJob);
- Rectangle2D pageFormatArea = getPageFormatArea(pageFormat);
+ BufferedImage bimg =
+ new BufferedImage(
+ (int)Math.round(pageFormat.getWidth()),
+ (int)Math.round(pageFormat.getHeight()),
+ BufferedImage.TYPE_INT_ARGB_PRE);
+ PeekGraphics peekGraphics =
+ createPeekGraphics(bimg.createGraphics(), printerJob);
+ Rectangle2D pageFormatArea =
+ getPageFormatArea(pageFormat);
initPrinterGraphics(peekGraphics, pageFormatArea);
// Do the assignment here!
@@ -741,7 +774,8 @@
// upcall from native
private static void detachPrintLoop(final long target, final long arg) {
- new ManagedLocalsThread(() -> _safePrintLoop(target, arg)).start();
+ new Thread(null, () -> _safePrintLoop(target, arg),
+ "PrintLoop", 0, false).start();
}
private static native void _safePrintLoop(long target, long arg);
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m Thu Apr 21 13:37:31 2016 -0700
@@ -312,9 +312,9 @@
static void nsPrintInfoToJavaPrinterJob(JNIEnv* env, NSPrintInfo* src, jobject dstPrinterJob, jobject dstPageable)
{
static JNF_MEMBER_CACHE(jm_setService, sjc_CPrinterJob, "setPrinterServiceFromNative", "(Ljava/lang/String;)V");
- static JNF_MEMBER_CACHE(jm_setCopies, sjc_CPrinterJob, "setCopies", "(I)V");
+ static JNF_MEMBER_CACHE(jm_setCopiesAttribute, sjc_CPrinterJob, "setCopiesAttribute", "(I)V");
static JNF_MEMBER_CACHE(jm_setCollated, sjc_CPrinterJob, "setCollated", "(Z)V");
- static JNF_MEMBER_CACHE(jm_setPageRange, sjc_CPrinterJob, "setPageRange", "(II)V");
+ static JNF_MEMBER_CACHE(jm_setPageRangeAttribute, sjc_CPrinterJob, "setPageRangeAttribute", "(IIZ)V");
// get the selected printer's name, and set the appropriate PrintService on the Java side
NSString *name = [[src printer] name];
@@ -327,7 +327,7 @@
NSNumber* nsCopies = [printingDictionary objectForKey:NSPrintCopies];
if ([nsCopies respondsToSelector:@selector(integerValue)])
{
- JNFCallVoidMethod(env, dstPrinterJob, jm_setCopies, [nsCopies integerValue]); // AWT_THREADING Safe (known object)
+ JNFCallVoidMethod(env, dstPrinterJob, jm_setCopiesAttribute, [nsCopies integerValue]); // AWT_THREADING Safe (known object)
}
NSNumber* nsCollated = [printingDictionary objectForKey:NSPrintMustCollate];
@@ -340,6 +340,7 @@
if ([nsPrintAllPages respondsToSelector:@selector(boolValue)])
{
jint jFirstPage = 0, jLastPage = java_awt_print_Pageable_UNKNOWN_NUMBER_OF_PAGES;
+ jboolean isRangeSet = false;
if (![nsPrintAllPages boolValue])
{
NSNumber* nsFirstPage = [printingDictionary objectForKey:NSPrintFirstPage];
@@ -353,9 +354,12 @@
{
jLastPage = [nsLastPage integerValue] - 1;
}
- }
+ isRangeSet = true;
+ }
+ JNFCallVoidMethod(env, dstPrinterJob, jm_setPageRangeAttribute,
+ jFirstPage, jLastPage, isRangeSet);
+ // AWT_THREADING Safe (known object)
- JNFCallVoidMethod(env, dstPrinterJob, jm_setPageRange, jFirstPage, jLastPage); // AWT_THREADING Safe (known object)
}
}
@@ -368,6 +372,8 @@
static JNF_MEMBER_CACHE(jm_isCollated, sjc_CPrinterJob, "isCollated", "()Z");
static JNF_MEMBER_CACHE(jm_getFromPage, sjc_CPrinterJob, "getFromPageAttrib", "()I");
static JNF_MEMBER_CACHE(jm_getToPage, sjc_CPrinterJob, "getToPageAttrib", "()I");
+ static JNF_MEMBER_CACHE(jm_getMinPage, sjc_CPrinterJob, "getMinPageAttrib", "()I");
+ static JNF_MEMBER_CACHE(jm_getMaxPage, sjc_CPrinterJob, "getMaxPageAttrib", "()I");
static JNF_MEMBER_CACHE(jm_getSelectAttrib, sjc_CPrinterJob, "getSelectAttrib", "()I");
static JNF_MEMBER_CACHE(jm_getNumberOfPages, jc_Pageable, "getNumberOfPages", "()I");
static JNF_MEMBER_CACHE(jm_getPageFormat, sjc_CPrinterJob, "getPageFormatFromAttributes", "()Ljava/awt/print/PageFormat;");
@@ -379,31 +385,33 @@
jboolean collated = JNFCallBooleanMethod(env, srcPrinterJob, jm_isCollated); // AWT_THREADING Safe (known object)
[printingDictionary setObject:[NSNumber numberWithBool:collated ? YES : NO] forKey:NSPrintMustCollate];
- jint jNumPages = JNFCallIntMethod(env, srcPageable, jm_getNumberOfPages); // AWT_THREADING Safe (!appKit)
- if (jNumPages != java_awt_print_Pageable_UNKNOWN_NUMBER_OF_PAGES)
- {
- jint selectID = JNFCallIntMethod(env, srcPrinterJob, jm_getSelectAttrib);
- if (selectID ==0) {
- [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintAllPages];
- } else if (selectID == 2) {
- // In Mac 10.7, Print ALL is deselected if PrintSelection is YES whether
- // NSPrintAllPages is YES or NO
- [printingDictionary setObject:[NSNumber numberWithBool:NO] forKey:NSPrintAllPages];
- [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintSelectionOnly];
- } else {
+ jint selectID = JNFCallIntMethod(env, srcPrinterJob, jm_getSelectAttrib);
+ jint fromPage = JNFCallIntMethod(env, srcPrinterJob, jm_getFromPage);
+ jint toPage = JNFCallIntMethod(env, srcPrinterJob, jm_getToPage);
+ if (selectID ==0) {
+ [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintAllPages];
+ } else if (selectID == 2) {
+ // In Mac 10.7, Print ALL is deselected if PrintSelection is YES whether
+ // NSPrintAllPages is YES or NO
+ [printingDictionary setObject:[NSNumber numberWithBool:NO] forKey:NSPrintAllPages];
+ [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintSelectionOnly];
+ } else {
+ jint minPage = JNFCallIntMethod(env, srcPrinterJob, jm_getMinPage);
+ jint maxPage = JNFCallIntMethod(env, srcPrinterJob, jm_getMaxPage);
+
+ // for PD_SELECTION or PD_NOSELECTION, check from/to page
+ // to determine which radio button to select
+ if (fromPage > minPage || toPage < maxPage) {
[printingDictionary setObject:[NSNumber numberWithBool:NO] forKey:NSPrintAllPages];
+ } else {
+ [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintAllPages];
}
+ }
- jint fromPage = JNFCallIntMethod(env, srcPrinterJob, jm_getFromPage);
- jint toPage = JNFCallIntMethod(env, srcPrinterJob, jm_getToPage);
- // setting fromPage and toPage will not be shown in the dialog if printing All pages
- [printingDictionary setObject:[NSNumber numberWithInteger:fromPage] forKey:NSPrintFirstPage];
- [printingDictionary setObject:[NSNumber numberWithInteger:toPage] forKey:NSPrintLastPage];
- }
- else
- {
- [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintAllPages];
- }
+ // setting fromPage and toPage will not be shown in the dialog if printing All pages
+ [printingDictionary setObject:[NSNumber numberWithInteger:fromPage] forKey:NSPrintFirstPage];
+ [printingDictionary setObject:[NSNumber numberWithInteger:toPage] forKey:NSPrintLastPage];
+
jobject page = JNFCallObjectMethod(env, srcPrinterJob, jm_getPageFormat);
if (page != NULL) {
javaPageFormatToNSPrintInfo(env, NULL, page, dst);
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CTrayIcon.m Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CTrayIcon.m Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, 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
@@ -39,18 +39,21 @@
* If the image of the specified size won't fit into the status bar,
* then scale it down proprtionally. Otherwise, leave it as is.
*/
-static NSSize ScaledImageSizeForStatusBar(NSSize imageSize) {
+static NSSize ScaledImageSizeForStatusBar(NSSize imageSize, BOOL autosize) {
NSRect imageRect = NSMakeRect(0.0, 0.0, imageSize.width, imageSize.height);
// There is a black line at the bottom of the status bar
// that we don't want to cover with image pixels.
- CGFloat desiredHeight = [[NSStatusBar systemStatusBar] thickness] - 1.0;
- CGFloat scaleFactor = MIN(1.0, desiredHeight/imageSize.height);
-
- imageRect.size.width *= scaleFactor;
- imageRect.size.height *= scaleFactor;
+ CGFloat desiredSize = [[NSStatusBar systemStatusBar] thickness] - 1.0;
+ if (autosize) {
+ imageRect.size.width = desiredSize;
+ imageRect.size.height = desiredSize;
+ } else {
+ CGFloat scaleFactor = MIN(1.0, desiredSize/imageSize.height);
+ imageRect.size.width *= scaleFactor;
+ imageRect.size.height *= scaleFactor;
+ }
imageRect = NSIntegralRect(imageRect);
-
return imageRect.size;
}
@@ -101,9 +104,9 @@
return peer;
}
-- (void) setImage:(NSImage *) imagePtr sizing:(BOOL)autosize{
+- (void) setImage:(NSImage *) imagePtr sizing:(BOOL)autosize {
NSSize imageSize = [imagePtr size];
- NSSize scaledSize = ScaledImageSizeForStatusBar(imageSize);
+ NSSize scaledSize = ScaledImageSizeForStatusBar(imageSize, autosize);
if (imageSize.width != scaledSize.width ||
imageSize.height != scaledSize.height) {
[imagePtr setSize: scaledSize];
--- a/jdk/src/java.desktop/share/classes/com/sun/imageio/stream/StreamCloser.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/stream/StreamCloser.java Thu Apr 21 13:37:31 2016 -0700
@@ -26,7 +26,6 @@
package com.sun.imageio.stream;
import sun.awt.util.ThreadGroupUtils;
-import sun.misc.ManagedLocalsThread;
import java.io.IOException;
import java.security.AccessController;
@@ -92,8 +91,8 @@
* Make its parent the top-level thread group.
*/
ThreadGroup tg = ThreadGroupUtils.getRootThreadGroup();
- streamCloser = new ManagedLocalsThread(tg,
- streamCloserRunnable);
+ streamCloser = new Thread(tg, streamCloserRunnable,
+ "StreamCloser", 0, false);
/* Set context class loader to null in order to avoid
* keeping a strong reference to an application classloader.
*/
--- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java Thu Apr 21 13:37:31 2016 -0700
@@ -64,7 +64,6 @@
import sun.awt.OSInfo;
import sun.awt.shell.ShellFolder;
import sun.font.FontUtilities;
-import sun.misc.ManagedLocalsThread;
import sun.security.action.GetPropertyAction;
import sun.swing.DefaultLayoutStyle;
@@ -2053,7 +2052,7 @@
if (audioRunnable != null) {
// Runnable appears to block until completed playing, hence
// start up another thread to handle playing.
- new ManagedLocalsThread(audioRunnable).start();
+ new Thread(null, audioRunnable, "Audio", 0, false).start();
}
}
}
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AudioFloatConverter.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AudioFloatConverter.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, 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,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.media.sound;
import java.nio.ByteBuffer;
@@ -319,8 +320,10 @@
float[] out_buff, int out_offset, int out_len) {
int ix = in_offset;
int ox = out_offset;
- for (int i = 0; i < out_len; i++)
- out_buff[ox++] = in_buff[ix++] * (1.0f / 127.0f);
+ for (int i = 0; i < out_len; i++) {
+ byte x = in_buff[ix++];
+ out_buff[ox++] = x > 0 ? x / 127.0f : x / 128.0f;
+ }
return out_buff;
}
@@ -328,8 +331,10 @@
byte[] out_buff, int out_offset) {
int ix = in_offset;
int ox = out_offset;
- for (int i = 0; i < in_len; i++)
- out_buff[ox++] = (byte) (in_buff[ix++] * 127.0f);
+ for (int i = 0; i < in_len; i++) {
+ final float x = in_buff[ix++];
+ out_buff[ox++] = (byte) (x > 0 ? x * 127 : x * 128);
+ }
return out_buff;
}
}
@@ -340,9 +345,10 @@
float[] out_buff, int out_offset, int out_len) {
int ix = in_offset;
int ox = out_offset;
- for (int i = 0; i < out_len; i++)
- out_buff[ox++] = ((in_buff[ix++] & 0xFF) - 127)
- * (1.0f / 127.0f);
+ for (int i = 0; i < out_len; i++) {
+ byte x = (byte) (in_buff[ix++] - 128);
+ out_buff[ox++] = x > 0 ? x / 127.0f : x / 128.0f;
+ }
return out_buff;
}
@@ -350,8 +356,10 @@
byte[] out_buff, int out_offset) {
int ix = in_offset;
int ox = out_offset;
- for (int i = 0; i < in_len; i++)
- out_buff[ox++] = (byte) (127 + in_buff[ix++] * 127.0f);
+ for (int i = 0; i < in_len; i++) {
+ float x = in_buff[ix++];
+ out_buff[ox++] = (byte) (128 + (x > 0 ? x * 127 : x * 128));
+ }
return out_buff;
}
}
@@ -369,10 +377,9 @@
int ix = in_offset;
int len = out_offset + out_len;
for (int ox = out_offset; ox < len; ox++) {
- out_buff[ox] = ((short) ((in_buff[ix++] & 0xFF) |
- (in_buff[ix++] << 8))) * (1.0f / 32767.0f);
+ short x = (short) (in_buff[ix++] & 0xFF | (in_buff[ix++] << 8));
+ out_buff[ox] = x > 0 ? x / 32767.0f : x / 32768.0f;
}
-
return out_buff;
}
@@ -381,7 +388,8 @@
int ox = out_offset;
int len = in_offset + in_len;
for (int ix = in_offset; ix < len; ix++) {
- int x = (int) (in_buff[ix] * 32767.0);
+ float f = in_buff[ix];
+ short x = (short) (f > 0 ? f * 32767 : f * 32768);
out_buff[ox++] = (byte) x;
out_buff[ox++] = (byte) (x >>> 8);
}
@@ -396,8 +404,8 @@
int ix = in_offset;
int ox = out_offset;
for (int i = 0; i < out_len; i++) {
- out_buff[ox++] = ((short) ((in_buff[ix++] << 8) |
- (in_buff[ix++] & 0xFF))) * (1.0f / 32767.0f);
+ short x = (short) ((in_buff[ix++] << 8) | (in_buff[ix++] & 0xFF));
+ out_buff[ox++] = x > 0 ? x / 32767.0f : x / 32768.0f;
}
return out_buff;
}
@@ -407,7 +415,8 @@
int ix = in_offset;
int ox = out_offset;
for (int i = 0; i < in_len; i++) {
- int x = (int) (in_buff[ix++] * 32767.0);
+ float f = in_buff[ix++];
+ short x = (short) (f > 0 ? f * 32767.0f : f * 32768.0f);
out_buff[ox++] = (byte) (x >>> 8);
out_buff[ox++] = (byte) x;
}
@@ -423,7 +432,8 @@
int ox = out_offset;
for (int i = 0; i < out_len; i++) {
int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8);
- out_buff[ox++] = (x - 32767) * (1.0f / 32767.0f);
+ x -= 32768;
+ out_buff[ox++] = x > 0 ? x / 32767.0f : x / 32768.0f;
}
return out_buff;
}
@@ -433,7 +443,8 @@
int ix = in_offset;
int ox = out_offset;
for (int i = 0; i < in_len; i++) {
- int x = 32767 + (int) (in_buff[ix++] * 32767.0);
+ float f = in_buff[ix++];
+ int x = 32768 + (int) (f > 0 ? f * 32767 : f * 32768);
out_buff[ox++] = (byte) x;
out_buff[ox++] = (byte) (x >>> 8);
}
@@ -449,7 +460,8 @@
int ox = out_offset;
for (int i = 0; i < out_len; i++) {
int x = ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF);
- out_buff[ox++] = (x - 32767) * (1.0f / 32767.0f);
+ x -= 32768;
+ out_buff[ox++] = x > 0 ? x / 32767.0f : x / 32768.0f;
}
return out_buff;
}
@@ -459,7 +471,8 @@
int ix = in_offset;
int ox = out_offset;
for (int i = 0; i < in_len; i++) {
- int x = 32767 + (int) (in_buff[ix++] * 32767.0);
+ float f = in_buff[ix++];
+ int x = 32768 + (int) (f > 0 ? f * 32767 : f * 32768);
out_buff[ox++] = (byte) (x >>> 8);
out_buff[ox++] = (byte) x;
}
@@ -484,7 +497,7 @@
| ((in_buff[ix++] & 0xFF) << 16);
if (x > 0x7FFFFF)
x -= 0x1000000;
- out_buff[ox++] = x * (1.0f / (float)0x7FFFFF);
+ out_buff[ox++] = x > 0 ? x / 8388607.0f : x / 8388608.0f;
}
return out_buff;
}
@@ -494,7 +507,8 @@
int ix = in_offset;
int ox = out_offset;
for (int i = 0; i < in_len; i++) {
- int x = (int) (in_buff[ix++] * (float)0x7FFFFF);
+ float f = in_buff[ix++];
+ int x = (int) (f > 0 ? f * 8388607.0f : f * 8388608.0f);
if (x < 0)
x += 0x1000000;
out_buff[ox++] = (byte) x;
@@ -516,7 +530,7 @@
| ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF);
if (x > 0x7FFFFF)
x -= 0x1000000;
- out_buff[ox++] = x * (1.0f / (float)0x7FFFFF);
+ out_buff[ox++] = x > 0 ? x / 8388607.0f : x / 8388608.0f;
}
return out_buff;
}
@@ -526,7 +540,8 @@
int ix = in_offset;
int ox = out_offset;
for (int i = 0; i < in_len; i++) {
- int x = (int) (in_buff[ix++] * (float)0x7FFFFF);
+ float f = in_buff[ix++];
+ int x = (int) (f > 0 ? f * 8388607.0f : f * 8388608.0f);
if (x < 0)
x += 0x1000000;
out_buff[ox++] = (byte) (x >>> 16);
@@ -546,8 +561,8 @@
for (int i = 0; i < out_len; i++) {
int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8)
| ((in_buff[ix++] & 0xFF) << 16);
- x -= 0x7FFFFF;
- out_buff[ox++] = x * (1.0f / (float)0x7FFFFF);
+ x -= 0x800000;
+ out_buff[ox++] = x > 0 ? x / 8388607.0f : x / 8388608.0f;
}
return out_buff;
}
@@ -557,8 +572,9 @@
int ix = in_offset;
int ox = out_offset;
for (int i = 0; i < in_len; i++) {
- int x = (int) (in_buff[ix++] * (float)0x7FFFFF);
- x += 0x7FFFFF;
+ float f = in_buff[ix++];
+ int x = (int) (f > 0 ? f * 8388607.0f : f * 8388608.0f);
+ x += 0x800000;
out_buff[ox++] = (byte) x;
out_buff[ox++] = (byte) (x >>> 8);
out_buff[ox++] = (byte) (x >>> 16);
@@ -576,8 +592,8 @@
for (int i = 0; i < out_len; i++) {
int x = ((in_buff[ix++] & 0xFF) << 16)
| ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF);
- x -= 0x7FFFFF;
- out_buff[ox++] = x * (1.0f / (float)0x7FFFFF);
+ x -= 0x800000;
+ out_buff[ox++] = x > 0 ? x / 8388607.0f : x / 8388608.0f;
}
return out_buff;
}
@@ -587,8 +603,9 @@
int ix = in_offset;
int ox = out_offset;
for (int i = 0; i < in_len; i++) {
- int x = (int) (in_buff[ix++] * (float)0x7FFFFF);
- x += 0x7FFFFF;
+ float f = in_buff[ix++];
+ int x = (int) (f > 0 ? f * 8388607.0f : f * 8388608.0f);
+ x += 8388608;
out_buff[ox++] = (byte) (x >>> 16);
out_buff[ox++] = (byte) (x >>> 8);
out_buff[ox++] = (byte) x;
@@ -673,7 +690,7 @@
int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8) |
((in_buff[ix++] & 0xFF) << 16) |
((in_buff[ix++] & 0xFF) << 24);
- x -= 0x7FFFFFFF;
+ x -= 0x80000000;
out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF);
}
return out_buff;
@@ -685,7 +702,7 @@
int ox = out_offset;
for (int i = 0; i < in_len; i++) {
int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF);
- x += 0x7FFFFFFF;
+ x += 0x80000000;
out_buff[ox++] = (byte) x;
out_buff[ox++] = (byte) (x >>> 8);
out_buff[ox++] = (byte) (x >>> 16);
@@ -706,7 +723,7 @@
int x = ((in_buff[ix++] & 0xFF) << 24) |
((in_buff[ix++] & 0xFF) << 16) |
((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF);
- x -= 0x7FFFFFFF;
+ x -= 0x80000000;
out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF);
}
return out_buff;
@@ -718,7 +735,7 @@
int ox = out_offset;
for (int i = 0; i < in_len; i++) {
int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF);
- x += 0x7FFFFFFF;
+ x += 0x80000000;
out_buff[ox++] = (byte) (x >>> 24);
out_buff[ox++] = (byte) (x >>> 16);
out_buff[ox++] = (byte) (x >>> 8);
@@ -737,7 +754,7 @@
// PCM 32+ bit, signed, little-endian
private static class AudioFloatConversion32xSL extends AudioFloatConverter {
- final int xbytes;
+ private final int xbytes;
AudioFloatConversion32xSL(int xbytes) {
this.xbytes = xbytes;
@@ -778,7 +795,7 @@
// PCM 32+ bit, signed, big-endian
private static class AudioFloatConversion32xSB extends AudioFloatConverter {
- final int xbytes;
+ private final int xbytes;
AudioFloatConversion32xSB(int xbytes) {
this.xbytes = xbytes;
@@ -820,7 +837,7 @@
// PCM 32+ bit, unsigned, little-endian
private static class AudioFloatConversion32xUL extends AudioFloatConverter {
- final int xbytes;
+ private final int xbytes;
AudioFloatConversion32xUL(int xbytes) {
this.xbytes = xbytes;
@@ -835,7 +852,7 @@
int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8)
| ((in_buff[ix++] & 0xFF) << 16)
| ((in_buff[ix++] & 0xFF) << 24);
- x -= 0x7FFFFFFF;
+ x -= 0x80000000;
out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF);
}
return out_buff;
@@ -847,7 +864,7 @@
int ox = out_offset;
for (int i = 0; i < in_len; i++) {
int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF);
- x += 0x7FFFFFFF;
+ x += 0x80000000;
for (int j = 0; j < xbytes; j++) {
out_buff[ox++] = 0;
}
@@ -863,7 +880,7 @@
// PCM 32+ bit, unsigned, big-endian
private static class AudioFloatConversion32xUB extends AudioFloatConverter {
- final int xbytes;
+ private final int xbytes;
AudioFloatConversion32xUB(int xbytes) {
this.xbytes = xbytes;
@@ -878,7 +895,7 @@
((in_buff[ix++] & 0xFF) << 16) |
((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF);
ix += xbytes;
- x -= 2147483647;
+ x -= 0x80000000;
out_buff[ox++] = x * (1.0f / 2147483647.0f);
}
return out_buff;
@@ -889,8 +906,8 @@
int ix = in_offset;
int ox = out_offset;
for (int i = 0; i < in_len; i++) {
- int x = (int) (in_buff[ix++] * 2147483647.0);
- x += 2147483647;
+ int x = (int) (in_buff[ix++] * 2147483647.0f);
+ x += 0x80000000;
out_buff[ox++] = (byte) (x >>> 24);
out_buff[ox++] = (byte) (x >>> 16);
out_buff[ox++] = (byte) (x >>> 8);
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/JSSecurityManager.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/JSSecurityManager.java Thu Apr 21 13:37:31 2016 -0700
@@ -25,8 +25,6 @@
package com.sun.media.sound;
-import sun.misc.ManagedLocalsThread;
-
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.io.File;
@@ -145,12 +143,11 @@
static Thread createThread(final Runnable runnable,
final String threadName,
final boolean isDaemon, final int priority,
- final boolean doStart) {
- Thread thread = new ManagedLocalsThread(runnable);
+ final boolean doStart)
+ {
+ String name = (threadName != null) ? threadName : "JSSM Thread";
+ Thread thread = new Thread(null, runnable, threadName, 0, false);
- if (threadName != null) {
- thread.setName(threadName);
- }
thread.setDaemon(isDaemon);
if (priority >= 0) {
thread.setPriority(priority);
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/JavaSoundAudioClip.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/JavaSoundAudioClip.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, 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
@@ -232,7 +232,7 @@
} else if (sequencer != null) {
try {
sequencerloop = false;
- sequencer.addMetaEventListener(this);
+ sequencer.removeMetaEventListener(this);
sequencer.stop();
} catch (Exception e3) {
if (Printer.err) e3.printStackTrace();
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftAudioPusher.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftAudioPusher.java Thu Apr 21 13:37:31 2016 -0700
@@ -24,8 +24,6 @@
*/
package com.sun.media.sound;
-import sun.misc.ManagedLocalsThread;
-
import java.io.IOException;
import javax.sound.sampled.AudioInputStream;
@@ -55,7 +53,7 @@
if (active)
return;
active = true;
- audiothread = new ManagedLocalsThread(this);
+ audiothread = new Thread(null, this, "AudioPusher", 0, false);
audiothread.setDaemon(true);
audiothread.setPriority(Thread.MAX_PRIORITY);
audiothread.start();
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftJitterCorrector.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftJitterCorrector.java Thu Apr 21 13:37:31 2016 -0700
@@ -24,8 +24,6 @@
*/
package com.sun.media.sound;
-import sun.misc.ManagedLocalsThread;
-
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import java.io.EOFException;
@@ -216,7 +214,7 @@
}
};
- thread = new ManagedLocalsThread(runnable);
+ thread = new Thread(null, runnable, "JitterCorrector", 0, false);
thread.setDaemon(true);
thread.setPriority(Thread.MAX_PRIORITY);
thread.start();
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftSynthesizer.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftSynthesizer.java Thu Apr 21 13:37:31 2016 -0700
@@ -25,8 +25,6 @@
package com.sun.media.sound;
-import sun.misc.ManagedLocalsThread;
-
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
@@ -141,7 +139,7 @@
pusher = null;
jitter_stream = null;
sourceDataLine = null;
- new ManagedLocalsThread(runnable).start();
+ new Thread(null, runnable, "Synthesizer",0,false).start();
}
return len;
}
--- a/jdk/src/java.desktop/share/classes/java/awt/EventDispatchThread.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/java/awt/EventDispatchThread.java Thu Apr 21 13:37:31 2016 -0700
@@ -31,7 +31,6 @@
import java.util.ArrayList;
-import sun.misc.ManagedLocalsThread;
import sun.util.logging.PlatformLogger;
import sun.awt.dnd.SunDragSourceContextPeer;
@@ -55,7 +54,7 @@
*
* @since 1.1
*/
-class EventDispatchThread extends ManagedLocalsThread {
+class EventDispatchThread extends Thread {
private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.EventDispatchThread");
@@ -66,8 +65,16 @@
private ArrayList<EventFilter> eventFilters = new ArrayList<EventFilter>();
+ /**
+ * Must always call 5 args super-class constructor passing false
+ * to indicate not to inherit locals.
+ */
+ private EventDispatchThread() {
+ throw new UnsupportedOperationException("Must erase locals");
+ }
+
EventDispatchThread(ThreadGroup group, String name, EventQueue queue) {
- super(group, name);
+ super(group, null, name, 0, false);
setEventQueue(queue);
}
--- a/jdk/src/java.desktop/share/classes/java/awt/Font.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/java/awt/Font.java Thu Apr 21 13:37:31 2016 -0700
@@ -766,6 +766,49 @@
}
/**
+ * Returns true if any part of the specified text is from a
+ * complex script for which the implementation will need to invoke
+ * layout processing in order to render correctly when using
+ * {@link Graphics#drawString(String,int,int) drawString(String,int,int)}
+ * and other text rendering methods. Measurement of the text
+ * may similarly need the same extra processing.
+ * The {@code start} and {@code end} indices are provided so that
+ * the application can request only a subset of the text be considered.
+ * The last char index examined is at {@code "end-1"},
+ * i.e a request to examine the entire array would be
+ * <pre>
+ * {@code Font.textRequiresLayout(chars, 0, chars.length);}
+ * </pre>
+ * An application may find this information helpful in
+ * performance sensitive code.
+ * <p>
+ * Note that even if this method returns {@code false}, layout processing
+ * may still be invoked when used with any {@code Font}
+ * for which {@link #hasLayoutAttributes()} returns {@code true},
+ * so that method will need to be consulted for the specific font,
+ * in order to obtain an answer which accounts for such font attributes.
+ *
+ * @param chars the text.
+ * @param start the index of the first char to examine.
+ * @param end the ending index, exclusive.
+ * @return {@code true} if the specified text will need special layout.
+ * @throws NullPointerException if {@code chars} is null.
+ * @throws ArrayIndexOutOfBoundsException if {@code start} is negative or
+ * {@code end} is greater than the length of the {@code chars} array.
+ * @since 9
+ */
+ public static boolean textRequiresLayout(char[] chars,
+ int start, int end) {
+ if (chars == null) {
+ throw new NullPointerException("null char array");
+ }
+ if (start < 0 || end > chars.length) {
+ throw new ArrayIndexOutOfBoundsException("start < 0 or end > len");
+ }
+ return FontUtilities.isComplexScript(chars, start, end);
+ }
+
+ /**
* Returns a {@code Font} appropriate to the attributes.
* If {@code attributes} contains a {@code FONT} attribute
* with a valid {@code Font} as its value, it will be
--- a/jdk/src/java.desktop/share/classes/java/awt/image/PackedColorModel.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/java/awt/image/PackedColorModel.java Thu Apr 21 13:37:31 2016 -0700
@@ -404,9 +404,6 @@
PackedColorModel cm = (PackedColorModel) obj;
int numC = cm.getNumComponents();
- if (numC != numComponents) {
- return false;
- }
for(int i=0; i < numC; i++) {
if (maskArray[i] != cm.getMask(i)) {
return false;
--- a/jdk/src/java.desktop/share/classes/java/awt/image/Raster.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/java/awt/image/Raster.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -629,7 +629,8 @@
int scanlineStride,
int pixelStride,
int bandOffsets[],
- Point location) {
+ Point location)
+ {
if (dataBuffer == null) {
throw new NullPointerException("DataBuffer cannot be null");
}
@@ -645,15 +646,26 @@
bandOffsets);
switch(dataType) {
case DataBuffer.TYPE_BYTE:
- return new ByteInterleavedRaster(csm, dataBuffer, location);
+ if (dataBuffer instanceof DataBufferByte) {
+ return new ByteInterleavedRaster(csm,
+ (DataBufferByte) dataBuffer, location);
+ }
+ break;
case DataBuffer.TYPE_USHORT:
- return new ShortInterleavedRaster(csm, dataBuffer, location);
+ if (dataBuffer instanceof DataBufferUShort) {
+ return new ShortInterleavedRaster(csm,
+ (DataBufferUShort) dataBuffer, location);
+ }
+ break;
default:
throw new IllegalArgumentException("Unsupported data type " +
dataType);
}
+
+ // Create the generic raster
+ return new SunWritableRaster(csm, dataBuffer, location);
}
/**
@@ -691,7 +703,8 @@
int scanlineStride,
int bankIndices[],
int bandOffsets[],
- Point location) {
+ Point location)
+ {
if (dataBuffer == null) {
throw new NullPointerException("DataBuffer cannot be null");
}
@@ -713,18 +726,29 @@
switch(dataType) {
case DataBuffer.TYPE_BYTE:
- return new ByteBandedRaster(bsm, dataBuffer, location);
+ if (dataBuffer instanceof DataBufferByte) {
+ return new ByteBandedRaster(bsm,
+ (DataBufferByte) dataBuffer, location);
+ }
+ break;
case DataBuffer.TYPE_USHORT:
- return new ShortBandedRaster(bsm, dataBuffer, location);
+ if (dataBuffer instanceof DataBufferUShort) {
+ return new ShortBandedRaster(bsm,
+ (DataBufferUShort) dataBuffer, location);
+ }
+ break;
case DataBuffer.TYPE_INT:
- return new SunWritableRaster(bsm, dataBuffer, location);
+ break;
default:
throw new IllegalArgumentException("Unsupported data type " +
dataType);
}
+
+ // Create the generic raster
+ return new SunWritableRaster(bsm, dataBuffer, location);
}
/**
@@ -761,7 +785,8 @@
int w, int h,
int scanlineStride,
int bandMasks[],
- Point location) {
+ Point location)
+ {
if (dataBuffer == null) {
throw new NullPointerException("DataBuffer cannot be null");
}
@@ -776,18 +801,33 @@
switch(dataType) {
case DataBuffer.TYPE_BYTE:
- return new ByteInterleavedRaster(sppsm, dataBuffer, location);
+ if (dataBuffer instanceof DataBufferByte) {
+ return new ByteInterleavedRaster(sppsm,
+ (DataBufferByte) dataBuffer, location);
+ }
+ break;
case DataBuffer.TYPE_USHORT:
- return new ShortInterleavedRaster(sppsm, dataBuffer, location);
+ if (dataBuffer instanceof DataBufferUShort) {
+ return new ShortInterleavedRaster(sppsm,
+ (DataBufferUShort) dataBuffer, location);
+ }
+ break;
case DataBuffer.TYPE_INT:
- return new IntegerInterleavedRaster(sppsm, dataBuffer, location);
+ if (dataBuffer instanceof DataBufferInt) {
+ return new IntegerInterleavedRaster(sppsm,
+ (DataBufferInt) dataBuffer, location);
+ }
+ break;
default:
throw new IllegalArgumentException("Unsupported data type " +
dataType);
}
+
+ // Create the generic raster
+ return new SunWritableRaster(sppsm, dataBuffer, location);
}
/**
@@ -821,7 +861,8 @@
public static WritableRaster createPackedRaster(DataBuffer dataBuffer,
int w, int h,
int bitsPerPixel,
- Point location) {
+ Point location)
+ {
if (dataBuffer == null) {
throw new NullPointerException("DataBuffer cannot be null");
}
@@ -846,9 +887,10 @@
MultiPixelPackedSampleModel mppsm =
new MultiPixelPackedSampleModel(dataType, w, h, bitsPerPixel);
- if (dataType == DataBuffer.TYPE_BYTE &&
- (bitsPerPixel == 1 || bitsPerPixel == 2 || bitsPerPixel == 4)) {
- return new BytePackedRaster(mppsm, dataBuffer, location);
+ if (dataBuffer instanceof DataBufferByte &&
+ (bitsPerPixel == 1 || bitsPerPixel == 2 || bitsPerPixel == 4))
+ {
+ return new BytePackedRaster(mppsm, (DataBufferByte) dataBuffer, location);
} else {
return new SunWritableRaster(mppsm, dataBuffer, location);
}
@@ -878,7 +920,8 @@
*/
public static Raster createRaster(SampleModel sm,
DataBuffer db,
- Point location) {
+ Point location)
+ {
if ((sm == null) || (db == null)) {
throw new NullPointerException("SampleModel and DataBuffer cannot be null");
}
@@ -890,32 +933,53 @@
if (sm instanceof PixelInterleavedSampleModel) {
switch(dataType) {
- case DataBuffer.TYPE_BYTE:
- return new ByteInterleavedRaster(sm, db, location);
+ case DataBuffer.TYPE_BYTE:
+ if (db instanceof DataBufferByte) {
+ return new ByteInterleavedRaster(sm,
+ (DataBufferByte) db, location);
+ }
+ break;
- case DataBuffer.TYPE_USHORT:
- return new ShortInterleavedRaster(sm, db, location);
+ case DataBuffer.TYPE_USHORT:
+ if (db instanceof DataBufferUShort) {
+ return new ShortInterleavedRaster(sm,
+ (DataBufferUShort) db, location);
+ }
+ break;
}
} else if (sm instanceof SinglePixelPackedSampleModel) {
switch(dataType) {
- case DataBuffer.TYPE_BYTE:
- return new ByteInterleavedRaster(sm, db, location);
+ case DataBuffer.TYPE_BYTE:
+ if (db instanceof DataBufferByte) {
+ return new ByteInterleavedRaster(sm,
+ (DataBufferByte) db, location);
+ }
+ break;
- case DataBuffer.TYPE_USHORT:
- return new ShortInterleavedRaster(sm, db, location);
+ case DataBuffer.TYPE_USHORT:
+ if (db instanceof DataBufferUShort) {
+ return new ShortInterleavedRaster(sm,
+ (DataBufferUShort) db, location);
+ }
+ break;
- case DataBuffer.TYPE_INT:
- return new IntegerInterleavedRaster(sm, db, location);
+ case DataBuffer.TYPE_INT:
+ if (db instanceof DataBufferInt) {
+ return new IntegerInterleavedRaster(sm,
+ (DataBufferInt) db, location);
+ }
+ break;
}
} else if (sm instanceof MultiPixelPackedSampleModel &&
dataType == DataBuffer.TYPE_BYTE &&
- sm.getSampleSize(0) < 8) {
- return new BytePackedRaster(sm, db, location);
+ db instanceof DataBufferByte &&
+ sm.getSampleSize(0) < 8)
+ {
+ return new BytePackedRaster(sm, (DataBufferByte) db, location);
}
// we couldn't do anything special - do the generic thing
-
- return new Raster(sm,db,location);
+ return new Raster(sm, db, location);
}
/**
@@ -964,7 +1028,8 @@
*/
public static WritableRaster createWritableRaster(SampleModel sm,
DataBuffer db,
- Point location) {
+ Point location)
+ {
if ((sm == null) || (db == null)) {
throw new NullPointerException("SampleModel and DataBuffer cannot be null");
}
@@ -976,32 +1041,53 @@
if (sm instanceof PixelInterleavedSampleModel) {
switch(dataType) {
- case DataBuffer.TYPE_BYTE:
- return new ByteInterleavedRaster(sm, db, location);
+ case DataBuffer.TYPE_BYTE:
+ if (db instanceof DataBufferByte) {
+ return new ByteInterleavedRaster(sm,
+ (DataBufferByte) db, location);
+ }
+ break;
- case DataBuffer.TYPE_USHORT:
- return new ShortInterleavedRaster(sm, db, location);
+ case DataBuffer.TYPE_USHORT:
+ if (db instanceof DataBufferUShort) {
+ return new ShortInterleavedRaster(sm,
+ (DataBufferUShort) db, location);
+ }
+ break;
}
} else if (sm instanceof SinglePixelPackedSampleModel) {
switch(dataType) {
- case DataBuffer.TYPE_BYTE:
- return new ByteInterleavedRaster(sm, db, location);
+ case DataBuffer.TYPE_BYTE:
+ if (db instanceof DataBufferByte) {
+ return new ByteInterleavedRaster(sm,
+ (DataBufferByte) db, location);
+ }
+ break;
- case DataBuffer.TYPE_USHORT:
- return new ShortInterleavedRaster(sm, db, location);
+ case DataBuffer.TYPE_USHORT:
+ if (db instanceof DataBufferUShort) {
+ return new ShortInterleavedRaster(sm,
+ (DataBufferUShort) db, location);
+ }
+ break;
- case DataBuffer.TYPE_INT:
- return new IntegerInterleavedRaster(sm, db, location);
+ case DataBuffer.TYPE_INT:
+ if (db instanceof DataBufferInt) {
+ return new IntegerInterleavedRaster(sm,
+ (DataBufferInt) db, location);
+ }
+ break;
}
} else if (sm instanceof MultiPixelPackedSampleModel &&
dataType == DataBuffer.TYPE_BYTE &&
- sm.getSampleSize(0) < 8) {
- return new BytePackedRaster(sm, db, location);
+ db instanceof DataBufferByte &&
+ sm.getSampleSize(0) < 8)
+ {
+ return new BytePackedRaster(sm, (DataBufferByte) db, location);
}
// we couldn't do anything special - do the generic thing
-
- return new SunWritableRaster(sm,db,location);
+ return new SunWritableRaster(sm, db, location);
}
/**
--- a/jdk/src/java.desktop/share/classes/java/awt/image/renderable/RenderableImageProducer.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/java/awt/image/renderable/RenderableImageProducer.java Thu Apr 21 13:37:31 2016 -0700
@@ -35,8 +35,6 @@
package java.awt.image.renderable;
-import sun.misc.ManagedLocalsThread;
-
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.ImageConsumer;
@@ -137,7 +135,7 @@
addConsumer(ic);
// Need to build a runnable object for the Thread.
String name = "RenderableImageProducer Thread";
- Thread thread = new ManagedLocalsThread(this, name);
+ Thread thread = new Thread(null, this, name, 0, false);
thread.start();
}
--- a/jdk/src/java.desktop/share/classes/javax/imageio/ImageIO.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/ImageIO.java Thu Apr 21 13:37:31 2016 -0700
@@ -1294,7 +1294,8 @@
*
* @exception IllegalArgumentException if {@code input} is
* {@code null}.
- * @exception IOException if an error occurs during reading.
+ * @exception IOException if an error occurs during reading or when not
+ * able to create required ImageInputStream.
*/
public static BufferedImage read(File input) throws IOException {
if (input == null) {
@@ -1344,7 +1345,8 @@
*
* @exception IllegalArgumentException if {@code input} is
* {@code null}.
- * @exception IOException if an error occurs during reading.
+ * @exception IOException if an error occurs during reading or when not
+ * able to create required ImageInputStream.
*/
public static BufferedImage read(InputStream input) throws IOException {
if (input == null) {
@@ -1352,6 +1354,9 @@
}
ImageInputStream stream = createImageInputStream(input);
+ if (stream == null) {
+ throw new IIOException("Can't create an ImageInputStream!");
+ }
BufferedImage bi = read(stream);
if (bi == null) {
stream.close();
@@ -1384,7 +1389,8 @@
*
* @exception IllegalArgumentException if {@code input} is
* {@code null}.
- * @exception IOException if an error occurs during reading.
+ * @exception IOException if an error occurs during reading or when not
+ * able to create required ImageInputStream.
*/
public static BufferedImage read(URL input) throws IOException {
if (input == null) {
@@ -1398,6 +1404,14 @@
throw new IIOException("Can't get input stream from URL!", e);
}
ImageInputStream stream = createImageInputStream(istream);
+ if (stream == null) {
+ /* close the istream when stream is null so that if user has
+ * given filepath as URL he can delete it, otherwise stream will
+ * be open to that file and he will not be able to delete it.
+ */
+ istream.close();
+ throw new IIOException("Can't create an ImageInputStream!");
+ }
BufferedImage bi;
try {
bi = read(stream);
@@ -1510,7 +1524,8 @@
*
* @exception IllegalArgumentException if any parameter is
* {@code null}.
- * @exception IOException if an error occurs during writing.
+ * @exception IOException if an error occurs during writing or when not
+ * able to create required ImageOutputStream.
*/
public static boolean write(RenderedImage im,
String formatName,
@@ -1518,7 +1533,6 @@
if (output == null) {
throw new IllegalArgumentException("output == null!");
}
- ImageOutputStream stream = null;
ImageWriter writer = getWriter(im, formatName);
if (writer == null) {
@@ -1528,13 +1542,11 @@
return false;
}
- try {
- output.delete();
- stream = createImageOutputStream(output);
- } catch (IOException e) {
- throw new IIOException("Can't create output stream!", e);
+ output.delete();
+ ImageOutputStream stream = createImageOutputStream(output);
+ if (stream == null) {
+ throw new IIOException("Can't create an ImageOutputStream!");
}
-
try {
return doWrite(im, writer, stream);
} finally {
@@ -1562,7 +1574,8 @@
*
* @exception IllegalArgumentException if any parameter is
* {@code null}.
- * @exception IOException if an error occurs during writing.
+ * @exception IOException if an error occurs during writing or when not
+ * able to create required ImageOutputStream.
*/
public static boolean write(RenderedImage im,
String formatName,
@@ -1570,13 +1583,10 @@
if (output == null) {
throw new IllegalArgumentException("output == null!");
}
- ImageOutputStream stream = null;
- try {
- stream = createImageOutputStream(output);
- } catch (IOException e) {
- throw new IIOException("Can't create output stream!", e);
+ ImageOutputStream stream = createImageOutputStream(output);
+ if (stream == null) {
+ throw new IIOException("Can't create an ImageOutputStream!");
}
-
try {
return doWrite(im, getWriter(im, formatName), stream);
} finally {
--- a/jdk/src/java.desktop/share/classes/javax/swing/JFileChooser.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/javax/swing/JFileChooser.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -26,13 +26,12 @@
import javax.swing.event.*;
import javax.swing.filechooser.*;
+import javax.swing.filechooser.FileFilter;
import javax.swing.plaf.FileChooserUI;
import javax.accessibility.*;
-import java.io.File;
-import java.io.ObjectOutputStream;
-import java.io.IOException;
+import java.io.*;
import java.util.Vector;
import java.awt.AWTEvent;
@@ -51,8 +50,6 @@
import java.beans.BeanProperty;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
-import java.io.InvalidObjectException;
-import java.io.ObjectInputStream;
import java.lang.ref.WeakReference;
/**
@@ -390,19 +387,7 @@
}
private void installHierarchyListener() {
- addHierarchyListener(new HierarchyListener() {
- @Override
- public void hierarchyChanged(HierarchyEvent e) {
- if ((e.getChangeFlags() & HierarchyEvent.PARENT_CHANGED)
- == HierarchyEvent.PARENT_CHANGED) {
- JFileChooser fc = JFileChooser.this;
- JRootPane rootPane = SwingUtilities.getRootPane(fc);
- if (rootPane != null) {
- rootPane.setDefaultButton(fc.getUI().getDefaultButton(fc));
- }
- }
- }
- });
+ addHierarchyListener(new FCHierarchyListener());
}
private void installShowFilesListener() {
@@ -2055,4 +2040,18 @@
} // inner class AccessibleJFileChooser
+ private class FCHierarchyListener implements HierarchyListener,
+ Serializable {
+ @Override
+ public void hierarchyChanged(HierarchyEvent e) {
+ if ((e.getChangeFlags() & HierarchyEvent.PARENT_CHANGED)
+ == HierarchyEvent.PARENT_CHANGED) {
+ JFileChooser fc = JFileChooser.this;
+ JRootPane rootPane = SwingUtilities.getRootPane(fc);
+ if (rootPane != null) {
+ rootPane.setDefaultButton(fc.getUI().getDefaultButton(fc));
+ }
+ }
+ }
+ }
}
--- a/jdk/src/java.desktop/share/classes/javax/swing/JMenu.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/javax/swing/JMenu.java Thu Apr 21 13:37:31 2016 -0700
@@ -1296,7 +1296,7 @@
* @return the array of menu items
*/
private MenuElement[] buildMenuElementArray(JMenu leaf) {
- Vector<MenuElement> elements = new Vector<MenuElement>();
+ Vector<MenuElement> elements = new Vector<>();
Component current = leaf.getPopupMenu();
JPopupMenu pop;
JMenu menu;
@@ -1314,11 +1314,14 @@
} else if (current instanceof JMenuBar) {
bar = (JMenuBar) current;
elements.insertElementAt(bar, 0);
- MenuElement me[] = new MenuElement[elements.size()];
- elements.copyInto(me);
- return me;
+ break;
+ } else {
+ break;
}
}
+ MenuElement me[] = new MenuElement[elements.size()];
+ elements.copyInto(me);
+ return me;
}
--- a/jdk/src/java.desktop/share/classes/javax/swing/JTable.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/javax/swing/JTable.java Thu Apr 21 13:37:31 2016 -0700
@@ -56,7 +56,6 @@
import javax.print.attribute.*;
import javax.print.PrintService;
-import sun.misc.ManagedLocalsThread;
import sun.reflect.misc.ReflectUtil;
import sun.swing.SwingUtilities2;
@@ -6375,7 +6374,7 @@
};
// start printing on another thread
- Thread th = new ManagedLocalsThread(runnable);
+ Thread th = new Thread(null, runnable, "JTablePrint", 0, false);
th.start();
printingStatus.showModal(true);
--- a/jdk/src/java.desktop/share/classes/javax/swing/TimerQueue.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/javax/swing/TimerQueue.java Thu Apr 21 13:37:31 2016 -0700
@@ -36,7 +36,6 @@
import java.util.concurrent.locks.*;
import java.util.concurrent.atomic.AtomicLong;
import sun.awt.AppContext;
-import sun.misc.ManagedLocalsThread;
/**
* Internal class to manage all Timers using one thread.
@@ -101,8 +100,8 @@
final ThreadGroup threadGroup = AppContext.getAppContext().getThreadGroup();
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
String name = "TimerQueue";
- Thread timerThread = new ManagedLocalsThread(threadGroup,
- this, name);
+ Thread timerThread =
+ new Thread(threadGroup, this, name, 0, false);
timerThread.setDaemon(true);
timerThread.setPriority(Thread.NORM_PRIORITY);
timerThread.start();
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java Thu Apr 21 13:37:31 2016 -0700
@@ -26,7 +26,6 @@
package javax.swing.plaf.basic;
import sun.awt.shell.ShellFolder;
-import sun.misc.ManagedLocalsThread;
import javax.swing.*;
import javax.swing.event.ListDataEvent;
@@ -271,7 +270,7 @@
this.currentDirectory = currentDirectory;
this.fid = fid;
String name = "Basic L&F File Loading Thread";
- this.loadThread = new ManagedLocalsThread(this, name);
+ this.loadThread = new Thread(null, this, name, 0, false);
this.loadThread.start();
}
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java Thu Apr 21 13:37:31 2016 -0700
@@ -797,9 +797,11 @@
if (invoker instanceof JPopupMenu) {
invoker = ((JPopupMenu)invoker).getInvoker();
}
- grabbedWindow = invoker instanceof Window?
- (Window)invoker :
- SwingUtilities.getWindowAncestor(invoker);
+ grabbedWindow = (invoker == null)
+ ? null
+ : ((invoker instanceof Window)
+ ? (Window) invoker
+ : SwingUtilities.getWindowAncestor(invoker));
if(grabbedWindow != null) {
if(tk instanceof sun.awt.SunToolkit) {
((sun.awt.SunToolkit)tk).grab(grabbedWindow);
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/nimbus/NimbusStyle.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/nimbus/NimbusStyle.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, 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
@@ -995,16 +995,7 @@
// StateInfo match, otherwise a StateInfo with
// SELECTED | ENABLED would match ENABLED, which we
// don't want.
-
- // This comes from BigInteger.bitCnt
- int bitCount = oState;
- bitCount -= (0xaaaaaaaa & bitCount) >>> 1;
- bitCount = (bitCount & 0x33333333) + ((bitCount >>> 2) &
- 0x33333333);
- bitCount = bitCount + (bitCount >>> 4) & 0x0f0f0f0f;
- bitCount += bitCount >>> 8;
- bitCount += bitCount >>> 16;
- bitCount = bitCount & 0xff;
+ int bitCount = Integer.bitCount(oState);
if (bitCount > bestCount) {
bestIndex = counter;
bestCount = bitCount;
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthStyle.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthStyle.java Thu Apr 21 13:37:31 2016 -0700
@@ -775,7 +775,7 @@
if (disabledColor == null || disabledColor instanceof UIResource) {
return getColorForState(context, type);
}
- } else if (c instanceof JLabel &&
+ } else if ((c instanceof JLabel || c instanceof JMenuItem) &&
(type == ColorType.FOREGROUND ||
type == ColorType.TEXT_FOREGROUND)) {
return getColorForState(context, type);
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java Thu Apr 21 13:37:31 2016 -0700
@@ -70,7 +70,6 @@
import sun.awt.AppContext;
-import sun.misc.ManagedLocalsThread;
import sun.swing.PrintingStatus;
import sun.swing.SwingUtilities2;
import sun.swing.text.TextComponentPrintable;
@@ -2353,7 +2352,8 @@
runnablePrinting.run();
} else {
if (isEventDispatchThread) {
- new ManagedLocalsThread(runnablePrinting).start();
+ new Thread(null, runnablePrinting,
+ "JTextComponentPrint", 0, false ).start();
printingStatus.showModal(true);
} else {
printingStatus.showModal(false);
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/LayoutQueue.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/LayoutQueue.java Thu Apr 21 13:37:31 2016 -0700
@@ -26,7 +26,6 @@
import java.util.Vector;
import sun.awt.AppContext;
-import sun.misc.ManagedLocalsThread;
/**
* A queue of text layout tasks.
@@ -92,7 +91,7 @@
}
} while (work != null);
};
- worker = new ManagedLocalsThread(workerRunnable, "text-layout");
+ worker = new Thread(null, workerRunnable, "text-layout", 0, false);
worker.setPriority(Thread.MIN_PRIORITY);
worker.start();
}
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/html/CSS.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/html/CSS.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, 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
@@ -1522,8 +1522,16 @@
current++;
}
last = current;
- while (current < length && !Character.isWhitespace
- (value.charAt(current))) {
+ int inParentheses = 0;
+ char ch;
+ while (current < length && (
+ !Character.isWhitespace(ch = value.charAt(current))
+ || inParentheses > 0)) {
+ if (ch == '(') {
+ inParentheses++;
+ } else if (ch == ')') {
+ inParentheses--;
+ }
current++;
}
if (last != current) {
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletClassLoader.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletClassLoader.java Thu Apr 21 13:37:31 2016 -0700
@@ -52,7 +52,6 @@
import java.security.PermissionCollection;
import sun.awt.AppContext;
import sun.awt.SunToolkit;
-import sun.misc.ManagedLocalsThread;
import sun.net.www.ParseUtil;
import sun.security.util.SecurityConstants;
@@ -858,13 +857,20 @@
* this operation to complete before continuing, wait for the notifyAll()
* operation on the syncObject to occur.
*/
-class AppContextCreator extends ManagedLocalsThread {
+class AppContextCreator extends Thread {
Object syncObject = new Object();
AppContext appContext = null;
volatile boolean created = false;
+ /**
+ * Must call the 5-args super-class constructor to erase locals.
+ */
+ private AppContextCreator() {
+ throw new UnsupportedOperationException("Must erase locals");
+ }
+
AppContextCreator(ThreadGroup group) {
- super(group, "AppContextCreator");
+ super(group, null, "AppContextCreator", 0, false);
}
public void run() {
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletPanel.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletPanel.java Thu Apr 21 13:37:31 2016 -0700
@@ -44,7 +44,6 @@
import sun.awt.EmbeddedFrame;
import sun.awt.SunToolkit;
import sun.awt.util.PerformanceLogger;
-import sun.misc.ManagedLocalsThread;
import sun.security.util.SecurityConstants;
/**
@@ -166,7 +165,7 @@
ThreadGroup appletGroup = loader.getThreadGroup();
- handler = new ManagedLocalsThread(appletGroup, this, "thread " + nm);
+ handler = new Thread(appletGroup, this, "thread " + nm, 0, false);
// set the context class loader for this thread
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
@@ -396,9 +395,8 @@
// until the loader thread terminates.
// (one way or another).
if (loaderThread == null) {
- // REMIND: do we want a name?
- //System.out.println("------------------- loading applet");
- setLoaderThread(new ManagedLocalsThread(this));
+ setLoaderThread(new Thread(null, this,
+ "AppletLoader", 0, false));
loaderThread.start();
// we get to go to sleep while this runs
loaderThread.join();
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletViewer.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletViewer.java Thu Apr 21 13:37:31 2016 -0700
@@ -38,7 +38,6 @@
import java.security.PrivilegedAction;
import sun.awt.SunToolkit;
import sun.awt.AppContext;
-import sun.misc.ManagedLocalsThread;
/**
* A frame to show the applet tag in.
@@ -854,7 +853,7 @@
//
final AppletPanel p = panel;
- new ManagedLocalsThread(new Runnable()
+ new Thread(null, new Runnable()
{
@Override
public void run()
@@ -867,7 +866,8 @@
appletSystemExit();
}
}
- }).start();
+ },
+ "AppletCloser", 0, false).start();
}
/**
@@ -890,7 +890,7 @@
// spawn a new thread to avoid blocking the event queue
// when calling appletShutdown.
//
- new ManagedLocalsThread(new Runnable()
+ new Thread(null, new Runnable()
{
@Override
public void run()
@@ -901,7 +901,8 @@
}
appletSystemExit();
}
- }).start();
+ },
+ "AppletQuit", 0, false).start();
}
/**
--- a/jdk/src/java.desktop/share/classes/sun/awt/AWTAutoShutdown.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/awt/AWTAutoShutdown.java Thu Apr 21 13:37:31 2016 -0700
@@ -34,7 +34,6 @@
import java.util.Set;
import sun.awt.util.ThreadGroupUtils;
-import sun.misc.ManagedLocalsThread;
import sun.util.logging.PlatformLogger;
/**
@@ -337,8 +336,8 @@
private void activateBlockerThread() {
AccessController.doPrivileged((PrivilegedAction<Thread>) () -> {
String name = "AWT-Shutdown";
- Thread thread = new ManagedLocalsThread(
- ThreadGroupUtils.getRootThreadGroup(), this, name);
+ Thread thread = new Thread(
+ ThreadGroupUtils.getRootThreadGroup(), this, name, 0, false);
thread.setContextClassLoader(null);
thread.setDaemon(false);
blockerThread = thread;
--- a/jdk/src/java.desktop/share/classes/sun/awt/AppContext.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/awt/AppContext.java Thu Apr 21 13:37:31 2016 -0700
@@ -46,7 +46,6 @@
import jdk.internal.misc.JavaAWTAccess;
import jdk.internal.misc.SharedSecrets;
-import sun.misc.ManagedLocalsThread;
import sun.util.logging.PlatformLogger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
@@ -598,8 +597,8 @@
}
public Thread run() {
- Thread t = new ManagedLocalsThread(appContext.getThreadGroup(),
- runnable, "AppContext Disposer");
+ Thread t = new Thread(appContext.getThreadGroup(),
+ runnable, "AppContext Disposer", 0, false);
t.setContextClassLoader(appContext.getContextClassLoader());
t.setPriority(Thread.NORM_PRIORITY + 1);
t.setDaemon(true);
--- a/jdk/src/java.desktop/share/classes/sun/awt/im/InputMethodManager.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/awt/im/InputMethodManager.java Thu Apr 21 13:37:31 2016 -0700
@@ -55,7 +55,6 @@
import java.util.prefs.Preferences;
import sun.awt.InputMethodSupport;
import sun.awt.SunToolkit;
-import sun.misc.ManagedLocalsThread;
/**
* {@code InputMethodManager} is an abstract class that manages the input
@@ -166,7 +165,8 @@
// to choose from. Otherwise, just keep the instance.
if (imm.hasMultipleInputMethods()) {
imm.initialize();
- Thread immThread = new ManagedLocalsThread(imm, threadName);
+ Thread immThread =
+ new Thread(null, imm, threadName, 0, false);
immThread.setDaemon(true);
immThread.setPriority(Thread.NORM_PRIORITY + 1);
immThread.start();
--- a/jdk/src/java.desktop/share/classes/sun/awt/image/ByteBandedRaster.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/awt/image/ByteBandedRaster.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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,7 +29,6 @@
import java.awt.image.RasterFormatException;
import java.awt.image.SampleModel;
import java.awt.image.BandedSampleModel;
-import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.Rectangle;
import java.awt.Point;
@@ -74,10 +73,9 @@
* @param sampleModel The SampleModel that specifies the layout.
* @param origin The Point that specifies the origin.
*/
- public ByteBandedRaster(SampleModel sampleModel,
- Point origin) {
+ public ByteBandedRaster(SampleModel sampleModel, Point origin) {
this(sampleModel,
- sampleModel.createDataBuffer(),
+ (DataBufferByte) sampleModel.createDataBuffer(),
new Rectangle(origin.x,
origin.y,
sampleModel.getWidth(),
@@ -93,12 +91,13 @@
* initialized and must be a DataBufferShort compatible with SampleModel.
* SampleModel must be of type BandedSampleModel.
* @param sampleModel The SampleModel that specifies the layout.
- * @param dataBuffer The DataBufferShort that contains the image data.
+ * @param dataBuffer The DataBufferByte that contains the image data.
* @param origin The Point that specifies the origin.
*/
public ByteBandedRaster(SampleModel sampleModel,
- DataBuffer dataBuffer,
- Point origin) {
+ DataBufferByte dataBuffer,
+ Point origin)
+ {
this(sampleModel, dataBuffer,
new Rectangle(origin.x , origin.y,
sampleModel.getWidth(),
@@ -119,39 +118,33 @@
* Note that this constructor should generally be called by other
* constructors or create methods, it should not be used directly.
* @param sampleModel The SampleModel that specifies the layout.
- * @param dataBuffer The DataBufferShort that contains the image data.
+ * @param dataBuffer The DataBufferByte that contains the image data.
* @param aRegion The Rectangle that specifies the image area.
* @param origin The Point that specifies the origin.
* @param parent The parent (if any) of this raster.
*/
public ByteBandedRaster(SampleModel sampleModel,
- DataBuffer dataBuffer,
+ DataBufferByte dataBuffer,
Rectangle aRegion,
Point origin,
- ByteBandedRaster parent) {
-
+ ByteBandedRaster parent)
+ {
super(sampleModel, dataBuffer, aRegion, origin, parent);
this.maxX = minX + width;
this.maxY = minY + height;
- if (!(dataBuffer instanceof DataBufferByte)) {
- throw new RasterFormatException("ByteBandedRaster must have" +
- "byte DataBuffers");
- }
- DataBufferByte dbb = (DataBufferByte)dataBuffer;
-
if (sampleModel instanceof BandedSampleModel) {
BandedSampleModel bsm = (BandedSampleModel)sampleModel;
this.scanlineStride = bsm.getScanlineStride();
int bankIndices[] = bsm.getBankIndices();
int bandOffsets[] = bsm.getBandOffsets();
- int dOffsets[] = dbb.getOffsets();
+ int dOffsets[] = dataBuffer.getOffsets();
dataOffsets = new int[bankIndices.length];
data = new byte[bankIndices.length][];
int xOffset = aRegion.x - origin.x;
int yOffset = aRegion.y - origin.y;
for (int i = 0; i < bankIndices.length; i++) {
- data[i] = stealData(dbb, bankIndices[i]);
+ data[i] = stealData(dataBuffer, bankIndices[i]);
dataOffsets[i] = dOffsets[bankIndices[i]] +
xOffset + yOffset*scanlineStride + bandOffsets[i];
}
@@ -672,7 +665,7 @@
int deltaY = y0 - y;
return new ByteBandedRaster(sm,
- dataBuffer,
+ (DataBufferByte) dataBuffer,
new Rectangle(x0,y0,width,height),
new Point(sampleModelTranslateX+deltaX,
sampleModelTranslateY+deltaY),
--- a/jdk/src/java.desktop/share/classes/sun/awt/image/ByteComponentRaster.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/awt/image/ByteComponentRaster.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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,6 @@
import java.awt.image.SampleModel;
import java.awt.image.ComponentSampleModel;
import java.awt.image.SinglePixelPackedSampleModel;
-import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.Rectangle;
import java.awt.Point;
@@ -94,7 +93,7 @@
*/
public ByteComponentRaster(SampleModel sampleModel, Point origin) {
this(sampleModel,
- sampleModel.createDataBuffer(),
+ (DataBufferByte) sampleModel.createDataBuffer(),
new Rectangle(origin.x,
origin.y,
sampleModel.getWidth(),
@@ -111,12 +110,13 @@
* SampleModel must be of type SinglePixelPackedSampleModel
* or ComponentSampleModel.
* @param sampleModel The SampleModel that specifies the layout.
- * @param dataBuffer The DataBufferShort that contains the image data.
+ * @param dataBuffer The DataBufferByte that contains the image data.
* @param origin The Point that specifies the origin.
*/
public ByteComponentRaster(SampleModel sampleModel,
- DataBuffer dataBuffer,
- Point origin) {
+ DataBufferByte dataBuffer,
+ Point origin)
+ {
this(sampleModel,
dataBuffer,
new Rectangle(origin.x,
@@ -141,33 +141,28 @@
* Note that this constructor should generally be called by other
* constructors or create methods, it should not be used directly.
* @param sampleModel The SampleModel that specifies the layout.
- * @param dataBuffer The DataBufferShort that contains the image data.
+ * @param dataBuffer The DataBufferByte that contains the image data.
* @param aRegion The Rectangle that specifies the image area.
* @param origin The Point that specifies the origin.
* @param parent The parent (if any) of this raster.
*/
public ByteComponentRaster(SampleModel sampleModel,
- DataBuffer dataBuffer,
- Rectangle aRegion,
- Point origin,
- ByteComponentRaster parent) {
+ DataBufferByte dataBuffer,
+ Rectangle aRegion,
+ Point origin,
+ ByteComponentRaster parent)
+ {
super(sampleModel, dataBuffer, aRegion, origin, parent);
this.maxX = minX + width;
this.maxY = minY + height;
- if (!(dataBuffer instanceof DataBufferByte)) {
- throw new RasterFormatException("ByteComponentRasters must have " +
- "byte DataBuffers");
- }
-
- DataBufferByte dbb = (DataBufferByte)dataBuffer;
- this.data = stealData(dbb, 0);
- if (dbb.getNumBanks() != 1) {
+ this.data = stealData(dataBuffer, 0);
+ if (dataBuffer.getNumBanks() != 1) {
throw new
RasterFormatException("DataBuffer for ByteComponentRasters"+
" must only have 1 bank.");
}
- int dbOffset = dbb.getOffset();
+ int dbOffset = dataBuffer.getOffset();
if (sampleModel instanceof ComponentSampleModel) {
ComponentSampleModel ism = (ComponentSampleModel)sampleModel;
@@ -823,7 +818,7 @@
int deltaY = y0 - y;
return new ByteComponentRaster(sm,
- dataBuffer,
+ (DataBufferByte) dataBuffer,
new Rectangle(x0, y0, width, height),
new Point(sampleModelTranslateX+deltaX,
sampleModelTranslateY+deltaY),
--- a/jdk/src/java.desktop/share/classes/sun/awt/image/ByteInterleavedRaster.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/awt/image/ByteInterleavedRaster.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, 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
@@ -31,7 +31,6 @@
import java.awt.image.ComponentSampleModel;
import java.awt.image.PixelInterleavedSampleModel;
import java.awt.image.SinglePixelPackedSampleModel;
-import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.Rectangle;
import java.awt.Point;
@@ -87,7 +86,7 @@
*/
public ByteInterleavedRaster(SampleModel sampleModel, Point origin) {
this(sampleModel,
- sampleModel.createDataBuffer(),
+ (DataBufferByte) sampleModel.createDataBuffer(),
new Rectangle(origin.x,
origin.y,
sampleModel.getWidth(),
@@ -104,12 +103,13 @@
* SampleModel must be of type SinglePixelPackedSampleModel
* or InterleavedSampleModel.
* @param sampleModel The SampleModel that specifies the layout.
- * @param dataBuffer The DataBufferShort that contains the image data.
+ * @param dataBuffer The DataBufferByte that contains the image data.
* @param origin The Point that specifies the origin.
*/
public ByteInterleavedRaster(SampleModel sampleModel,
- DataBuffer dataBuffer,
- Point origin) {
+ DataBufferByte dataBuffer,
+ Point origin)
+ {
this(sampleModel,
dataBuffer,
new Rectangle(origin.x,
@@ -178,27 +178,22 @@
* Note that this constructor should generally be called by other
* constructors or create methods, it should not be used directly.
* @param sampleModel The SampleModel that specifies the layout.
- * @param dataBuffer The DataBufferShort that contains the image data.
+ * @param dataBuffer The DataBufferByte that contains the image data.
* @param aRegion The Rectangle that specifies the image area.
* @param origin The Point that specifies the origin.
* @param parent The parent (if any) of this raster.
*/
public ByteInterleavedRaster(SampleModel sampleModel,
- DataBuffer dataBuffer,
- Rectangle aRegion,
- Point origin,
- ByteInterleavedRaster parent) {
+ DataBufferByte dataBuffer,
+ Rectangle aRegion,
+ Point origin,
+ ByteInterleavedRaster parent)
+ {
super(sampleModel, dataBuffer, aRegion, origin, parent);
this.maxX = minX + width;
this.maxY = minY + height;
- if (!(dataBuffer instanceof DataBufferByte)) {
- throw new RasterFormatException("ByteInterleavedRasters must have " +
- "byte DataBuffers");
- }
-
- DataBufferByte dbb = (DataBufferByte)dataBuffer;
- this.data = stealData(dbb, 0);
+ this.data = stealData(dataBuffer, 0);
int xOffset = aRegion.x - origin.x;
int yOffset = aRegion.y - origin.y;
@@ -221,7 +216,7 @@
this.scanlineStride = sppsm.getScanlineStride();
this.pixelStride = 1;
this.dataOffsets = new int[1];
- this.dataOffsets[0] = dbb.getOffset();
+ this.dataOffsets[0] = dataBuffer.getOffset();
dataOffsets[0] += xOffset*pixelStride+yOffset*scanlineStride;
} else {
throw new RasterFormatException("ByteInterleavedRasters must " +
@@ -1259,7 +1254,7 @@
int deltaY = y0 - y;
return new ByteInterleavedRaster(sm,
- dataBuffer,
+ (DataBufferByte) dataBuffer,
new Rectangle(x0, y0, width, height),
new Point(sampleModelTranslateX+deltaX,
sampleModelTranslateY+deltaY),
--- a/jdk/src/java.desktop/share/classes/sun/awt/image/BytePackedRaster.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/awt/image/BytePackedRaster.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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,7 +29,6 @@
import java.awt.image.RasterFormatException;
import java.awt.image.SampleModel;
import java.awt.image.MultiPixelPackedSampleModel;
-import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.Rectangle;
import java.awt.Point;
@@ -89,10 +88,9 @@
* @param sampleModel The SampleModel that specifies the layout.
* @param origin The Point that specified the origin.
*/
- public BytePackedRaster(SampleModel sampleModel,
- Point origin) {
+ public BytePackedRaster(SampleModel sampleModel, Point origin) {
this(sampleModel,
- sampleModel.createDataBuffer(),
+ (DataBufferByte) sampleModel.createDataBuffer(),
new Rectangle(origin.x,
origin.y,
sampleModel.getWidth(),
@@ -108,12 +106,13 @@
* initialized and must be a DataBufferByte compatible with SampleModel.
* SampleModel must be of type MultiPixelPackedSampleModel.
* @param sampleModel The SampleModel that specifies the layout.
- * @param dataBuffer The DataBufferShort that contains the image data.
+ * @param dataBuffer The DataBufferByte that contains the image data.
* @param origin The Point that specifies the origin.
*/
public BytePackedRaster(SampleModel sampleModel,
- DataBuffer dataBuffer,
- Point origin) {
+ DataBufferByte dataBuffer,
+ Point origin)
+ {
this(sampleModel,
dataBuffer,
new Rectangle(origin.x,
@@ -137,7 +136,7 @@
* Note that this constructor should generally be called by other
* constructors or create methods, it should not be used directly.
* @param sampleModel The SampleModel that specifies the layout.
- * @param dataBuffer The DataBufferShort that contains the image data.
+ * @param dataBuffer The DataBufferByte that contains the image data.
* @param aRegion The Rectangle that specifies the image area.
* @param origin The Point that specifies the origin.
* @param parent The parent (if any) of this raster.
@@ -146,26 +145,22 @@
* to requirements of this Raster type.
*/
public BytePackedRaster(SampleModel sampleModel,
- DataBuffer dataBuffer,
+ DataBufferByte dataBuffer,
Rectangle aRegion,
Point origin,
- BytePackedRaster parent){
+ BytePackedRaster parent)
+ {
super(sampleModel,dataBuffer,aRegion,origin, parent);
this.maxX = minX + width;
this.maxY = minY + height;
- if (!(dataBuffer instanceof DataBufferByte)) {
- throw new RasterFormatException("BytePackedRasters must have" +
- "byte DataBuffers");
- }
- DataBufferByte dbb = (DataBufferByte)dataBuffer;
- this.data = stealData(dbb, 0);
- if (dbb.getNumBanks() != 1) {
+ this.data = stealData(dataBuffer, 0);
+ if (dataBuffer.getNumBanks() != 1) {
throw new
RasterFormatException("DataBuffer for BytePackedRasters"+
" must only have 1 bank.");
}
- int dbOffset = dbb.getOffset();
+ int dbOffset = dataBuffer.getOffset();
if (sampleModel instanceof MultiPixelPackedSampleModel) {
MultiPixelPackedSampleModel mppsm =
@@ -1322,7 +1317,7 @@
int deltaY = y0 - y;
return new BytePackedRaster(sm,
- dataBuffer,
+ (DataBufferByte) dataBuffer,
new Rectangle(x0, y0, width, height),
new Point(sampleModelTranslateX+deltaX,
sampleModelTranslateY+deltaY),
--- a/jdk/src/java.desktop/share/classes/sun/awt/image/ImageFetcher.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/awt/image/ImageFetcher.java Thu Apr 21 13:37:31 2016 -0700
@@ -27,7 +27,6 @@
import java.util.Vector;
import sun.awt.AppContext;
-import sun.misc.ManagedLocalsThread;
/**
* An ImageFetcher is a thread used to fetch ImageFetchable objects.
@@ -42,7 +41,7 @@
* @author Jim Graham
* @author Fred Ecks
*/
-class ImageFetcher extends ManagedLocalsThread {
+class ImageFetcher extends Thread {
static final int HIGH_PRIORITY = 8;
static final int LOW_PRIORITY = 3;
static final int ANIM_PRIORITY = 2;
@@ -52,10 +51,17 @@
// queue before an ImageFetcher dies
/**
+ * We must only call the 5 args super() constructor passing
+ * in "false" to indicate to not inherit locals.
+ */
+ private ImageFetcher() {
+ throw new UnsupportedOperationException("Must erase locals");
+ }
+ /**
* Constructor for ImageFetcher -- only called by add() below.
*/
private ImageFetcher(ThreadGroup threadGroup, int index) {
- super(threadGroup, "Image Fetcher " + index);
+ super(threadGroup, null, "Image Fetcher " + index, 0, false);
setDaemon(true);
}
--- a/jdk/src/java.desktop/share/classes/sun/awt/image/IntegerComponentRaster.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/awt/image/IntegerComponentRaster.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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,7 +29,6 @@
import java.awt.image.RasterFormatException;
import java.awt.image.SampleModel;
import java.awt.image.SinglePixelPackedSampleModel;
-import java.awt.image.DataBuffer;
import java.awt.image.DataBufferInt;
import java.awt.Rectangle;
import java.awt.Point;
@@ -107,10 +106,9 @@
* @param sampleModel The SampleModel that specifies the layout.
* @param origin The Point that specified the origin.
*/
- public IntegerComponentRaster(SampleModel sampleModel,
- Point origin) {
+ public IntegerComponentRaster(SampleModel sampleModel, Point origin) {
this(sampleModel,
- sampleModel.createDataBuffer(),
+ (DataBufferInt) sampleModel.createDataBuffer(),
new Rectangle(origin.x,
origin.y,
sampleModel.getWidth(),
@@ -130,8 +128,9 @@
* @param origin The Point that specifies the origin.
*/
public IntegerComponentRaster(SampleModel sampleModel,
- DataBuffer dataBuffer,
- Point origin) {
+ DataBufferInt dataBuffer,
+ Point origin)
+ {
this(sampleModel,
dataBuffer,
new Rectangle(origin.x,
@@ -161,24 +160,21 @@
* @param parent The parent (if any) of this raster.
*/
public IntegerComponentRaster(SampleModel sampleModel,
- DataBuffer dataBuffer,
- Rectangle aRegion,
- Point origin,
- IntegerComponentRaster parent){
+ DataBufferInt dataBuffer,
+ Rectangle aRegion,
+ Point origin,
+ IntegerComponentRaster parent)
+ {
super(sampleModel,dataBuffer,aRegion,origin,parent);
this.maxX = minX + width;
this.maxY = minY + height;
- if (!(dataBuffer instanceof DataBufferInt)) {
- throw new RasterFormatException("IntegerComponentRasters must have" +
- "integer DataBuffers");
- }
- DataBufferInt dbi = (DataBufferInt)dataBuffer;
- if (dbi.getNumBanks() != 1) {
+
+ if (dataBuffer.getNumBanks() != 1) {
throw new
RasterFormatException("DataBuffer for IntegerComponentRasters"+
" must only have 1 bank.");
}
- this.data = stealData(dbi, 0);
+ this.data = stealData(dataBuffer, 0);
if (sampleModel instanceof SinglePixelPackedSampleModel) {
SinglePixelPackedSampleModel sppsm =
@@ -197,7 +193,7 @@
this.scanlineStride = sppsm.getScanlineStride();
this.pixelStride = 1;
this.dataOffsets = new int[1];
- this.dataOffsets[0] = dbi.getOffset();
+ this.dataOffsets[0] = dataBuffer.getOffset();
this.bandOffset = this.dataOffsets[0];
int xOffset = aRegion.x - origin.x;
int yOffset = aRegion.y - origin.y;
@@ -569,7 +565,7 @@
int deltaY = y0 - y;
return new IntegerComponentRaster(sm,
- dataBuffer,
+ (DataBufferInt) dataBuffer,
new Rectangle(x0,y0,width,height),
new Point(sampleModelTranslateX+deltaX,
sampleModelTranslateY+deltaY),
--- a/jdk/src/java.desktop/share/classes/sun/awt/image/IntegerInterleavedRaster.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/awt/image/IntegerInterleavedRaster.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, 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,7 +29,6 @@
import java.awt.image.RasterFormatException;
import java.awt.image.SampleModel;
import java.awt.image.SinglePixelPackedSampleModel;
-import java.awt.image.DataBuffer;
import java.awt.image.DataBufferInt;
import java.awt.Rectangle;
import java.awt.Point;
@@ -67,10 +66,9 @@
* @param sampleModel The SampleModel that specifies the layout.
* @param origin The Point that specified the origin.
*/
- public IntegerInterleavedRaster(SampleModel sampleModel,
- Point origin) {
+ public IntegerInterleavedRaster(SampleModel sampleModel, Point origin) {
this(sampleModel,
- sampleModel.createDataBuffer(),
+ (DataBufferInt) sampleModel.createDataBuffer(),
new Rectangle(origin.x,
origin.y,
sampleModel.getWidth(),
@@ -90,8 +88,9 @@
* @param origin The Point that specifies the origin.
*/
public IntegerInterleavedRaster(SampleModel sampleModel,
- DataBuffer dataBuffer,
- Point origin) {
+ DataBufferInt dataBuffer,
+ Point origin)
+ {
this(sampleModel,
dataBuffer,
new Rectangle(origin.x,
@@ -121,19 +120,16 @@
* @param parent The parent (if any) of this raster.
*/
public IntegerInterleavedRaster(SampleModel sampleModel,
- DataBuffer dataBuffer,
- Rectangle aRegion,
- Point origin,
- IntegerInterleavedRaster parent){
+ DataBufferInt dataBuffer,
+ Rectangle aRegion,
+ Point origin,
+ IntegerInterleavedRaster parent)
+ {
super(sampleModel,dataBuffer,aRegion,origin,parent);
this.maxX = minX + width;
this.maxY = minY + height;
- if (!(dataBuffer instanceof DataBufferInt)) {
- throw new RasterFormatException("IntegerInterleavedRasters must have" +
- "integer DataBuffers");
- }
- DataBufferInt dbi = (DataBufferInt)dataBuffer;
- this.data = stealData(dbi, 0);
+
+ this.data = stealData(dataBuffer, 0);
if (sampleModel instanceof SinglePixelPackedSampleModel) {
SinglePixelPackedSampleModel sppsm =
@@ -141,7 +137,7 @@
this.scanlineStride = sppsm.getScanlineStride();
this.pixelStride = 1;
this.dataOffsets = new int[1];
- this.dataOffsets[0] = dbi.getOffset();
+ this.dataOffsets[0] = dataBuffer.getOffset();
this.bandOffset = this.dataOffsets[0];
int xOffset = aRegion.x - origin.x;
int yOffset = aRegion.y - origin.y;
@@ -481,7 +477,7 @@
int deltaY = y0 - y;
return new IntegerInterleavedRaster(sm,
- dataBuffer,
+ (DataBufferInt) dataBuffer,
new Rectangle(x0,y0,width,height),
new Point(sampleModelTranslateX+deltaX,
sampleModelTranslateY+deltaY),
--- a/jdk/src/java.desktop/share/classes/sun/awt/image/ShortBandedRaster.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/awt/image/ShortBandedRaster.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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,7 +29,6 @@
import java.awt.image.RasterFormatException;
import java.awt.image.SampleModel;
import java.awt.image.BandedSampleModel;
-import java.awt.image.DataBuffer;
import java.awt.image.DataBufferUShort;
import java.awt.Rectangle;
import java.awt.Point;
@@ -72,10 +71,9 @@
* @param sampleModel The SampleModel that specifies the layout.
* @param origin The Point that specified the origin.
*/
- public ShortBandedRaster(SampleModel sampleModel,
- Point origin) {
+ public ShortBandedRaster(SampleModel sampleModel, Point origin) {
this(sampleModel,
- sampleModel.createDataBuffer(),
+ (DataBufferUShort) sampleModel.createDataBuffer(),
new Rectangle(origin.x,
origin.y,
sampleModel.getWidth(),
@@ -95,8 +93,9 @@
* @param origin The Point that specifies the origin.
*/
public ShortBandedRaster(SampleModel sampleModel,
- DataBuffer dataBuffer,
- Point origin) {
+ DataBufferUShort dataBuffer,
+ Point origin)
+ {
this(sampleModel, dataBuffer,
new Rectangle(origin.x, origin.y,
sampleModel.getWidth(),
@@ -123,32 +122,27 @@
* @param parent The parent (if any) of this raster.
*/
public ShortBandedRaster(SampleModel sampleModel,
- DataBuffer dataBuffer,
- Rectangle aRegion,
- Point origin,
- ShortBandedRaster parent) {
-
+ DataBufferUShort dataBuffer,
+ Rectangle aRegion,
+ Point origin,
+ ShortBandedRaster parent)
+ {
super(sampleModel, dataBuffer, aRegion, origin, parent);
this.maxX = minX + width;
this.maxY = minY + height;
- if (!(dataBuffer instanceof DataBufferUShort)) {
- throw new RasterFormatException("ShortBandedRaster must have " +
- "ushort DataBuffers");
- }
- DataBufferUShort dbus = (DataBufferUShort)dataBuffer;
if (sampleModel instanceof BandedSampleModel) {
BandedSampleModel bsm = (BandedSampleModel)sampleModel;
this.scanlineStride = bsm.getScanlineStride();
int bankIndices[] = bsm.getBankIndices();
int bandOffsets[] = bsm.getBandOffsets();
- int dOffsets[] = dbus.getOffsets();
+ int dOffsets[] = dataBuffer.getOffsets();
dataOffsets = new int[bankIndices.length];
data = new short[bankIndices.length][];
int xOffset = aRegion.x - origin.x;
int yOffset = aRegion.y - origin.y;
for (int i = 0; i < bankIndices.length; i++) {
- data[i] = stealData(dbus, bankIndices[i]);
+ data[i] = stealData(dataBuffer, bankIndices[i]);
dataOffsets[i] = dOffsets[bankIndices[i]] +
xOffset + yOffset*scanlineStride + bandOffsets[i];
}
@@ -670,7 +664,7 @@
int deltaY = y0 - y;
return new ShortBandedRaster(sm,
- dataBuffer,
+ (DataBufferUShort) dataBuffer,
new Rectangle(x0, y0, width, height),
new Point(sampleModelTranslateX+deltaX,
sampleModelTranslateY+deltaY),
--- a/jdk/src/java.desktop/share/classes/sun/awt/image/ShortComponentRaster.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/awt/image/ShortComponentRaster.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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,6 @@
import java.awt.image.SampleModel;
import java.awt.image.ComponentSampleModel;
import java.awt.image.SinglePixelPackedSampleModel;
-import java.awt.image.DataBuffer;
import java.awt.image.DataBufferUShort;
import java.awt.Rectangle;
import java.awt.Point;
@@ -94,7 +93,7 @@
*/
public ShortComponentRaster(SampleModel sampleModel, Point origin) {
this(sampleModel,
- sampleModel.createDataBuffer(),
+ (DataBufferUShort) sampleModel.createDataBuffer(),
new Rectangle(origin.x,
origin.y,
sampleModel.getWidth(),
@@ -115,8 +114,9 @@
* @param origin The Point that specifies the origin.
*/
public ShortComponentRaster(SampleModel sampleModel,
- DataBuffer dataBuffer,
- Point origin) {
+ DataBufferUShort dataBuffer,
+ Point origin)
+ {
this(sampleModel,
dataBuffer,
new Rectangle(origin.x,
@@ -146,28 +146,22 @@
* @param parent The parent (if any) of this raster.
*/
public ShortComponentRaster(SampleModel sampleModel,
- DataBuffer dataBuffer,
- Rectangle aRegion,
- Point origin,
- ShortComponentRaster parent) {
-
+ DataBufferUShort dataBuffer,
+ Rectangle aRegion,
+ Point origin,
+ ShortComponentRaster parent)
+ {
super(sampleModel, dataBuffer, aRegion, origin, parent);
this.maxX = minX + width;
this.maxY = minY + height;
- if(!(dataBuffer instanceof DataBufferUShort)) {
- throw new RasterFormatException("ShortComponentRasters must have "+
- "short DataBuffers");
- }
-
- DataBufferUShort dbus = (DataBufferUShort)dataBuffer;
- this.data = stealData(dbus, 0);
- if (dbus.getNumBanks() != 1) {
+ this.data = stealData(dataBuffer, 0);
+ if (dataBuffer.getNumBanks() != 1) {
throw new
RasterFormatException("DataBuffer for ShortComponentRasters"+
" must only have 1 bank.");
}
- int dbOffset = dbus.getOffset();
+ int dbOffset = dataBuffer.getOffset();
if (sampleModel instanceof ComponentSampleModel) {
ComponentSampleModel csm = (ComponentSampleModel)sampleModel;
@@ -758,7 +752,7 @@
int deltaY = y0 - y;
return new ShortComponentRaster(sm,
- dataBuffer,
+ (DataBufferUShort) dataBuffer,
new Rectangle(x0, y0, width, height),
new Point(sampleModelTranslateX+deltaX,
sampleModelTranslateY+deltaY),
--- a/jdk/src/java.desktop/share/classes/sun/awt/image/ShortInterleavedRaster.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/awt/image/ShortInterleavedRaster.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, 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
@@ -31,7 +31,6 @@
import java.awt.image.ComponentSampleModel;
import java.awt.image.PixelInterleavedSampleModel;
import java.awt.image.SinglePixelPackedSampleModel;
-import java.awt.image.DataBuffer;
import java.awt.image.DataBufferUShort;
import java.awt.Rectangle;
import java.awt.Point;
@@ -71,7 +70,7 @@
*/
public ShortInterleavedRaster(SampleModel sampleModel, Point origin) {
this(sampleModel,
- sampleModel.createDataBuffer(),
+ (DataBufferUShort) sampleModel.createDataBuffer(),
new Rectangle(origin.x,
origin.y,
sampleModel.getWidth(),
@@ -92,8 +91,9 @@
* @param origin The Point that specifies the origin.
*/
public ShortInterleavedRaster(SampleModel sampleModel,
- DataBuffer dataBuffer,
- Point origin) {
+ DataBufferUShort dataBuffer,
+ Point origin)
+ {
this(sampleModel,
dataBuffer,
new Rectangle(origin.x,
@@ -123,22 +123,17 @@
* @param parent The parent (if any) of this raster.
*/
public ShortInterleavedRaster(SampleModel sampleModel,
- DataBuffer dataBuffer,
- Rectangle aRegion,
- Point origin,
- ShortInterleavedRaster parent) {
+ DataBufferUShort dataBuffer,
+ Rectangle aRegion,
+ Point origin,
+ ShortInterleavedRaster parent)
+ {
super(sampleModel, dataBuffer, aRegion, origin, parent);
this.maxX = minX + width;
this.maxY = minY + height;
- if(!(dataBuffer instanceof DataBufferUShort)) {
- throw new RasterFormatException("ShortInterleavedRasters must "+
- "have ushort DataBuffers");
- }
-
- DataBufferUShort dbus = (DataBufferUShort)dataBuffer;
- this.data = stealData(dbus, 0);
+ this.data = stealData(dataBuffer, 0);
// REMIND: need case for interleaved ComponentSampleModel
if ((sampleModel instanceof PixelInterleavedSampleModel) ||
@@ -160,7 +155,7 @@
this.scanlineStride = sppsm.getScanlineStride();
this.pixelStride = 1;
this.dataOffsets = new int[1];
- this.dataOffsets[0] = dbus.getOffset();
+ this.dataOffsets[0] = dataBuffer.getOffset();
int xOffset = aRegion.x - origin.x;
int yOffset = aRegion.y - origin.y;
dataOffsets[0] += xOffset+yOffset*scanlineStride;
@@ -730,7 +725,7 @@
int deltaY = y0 - y;
return new ShortInterleavedRaster(sm,
- dataBuffer,
+ (DataBufferUShort) dataBuffer,
new Rectangle(x0, y0, width, height),
new Point(sampleModelTranslateX+deltaX,
sampleModelTranslateY+deltaY),
--- a/jdk/src/java.desktop/share/classes/sun/font/CreatedFontTracker.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/font/CreatedFontTracker.java Thu Apr 21 13:37:31 2016 -0700
@@ -36,7 +36,6 @@
import sun.awt.AppContext;
import sun.awt.util.ThreadGroupUtils;
-import sun.misc.ManagedLocalsThread;
public class CreatedFontTracker {
@@ -122,8 +121,8 @@
* Make its parent the top-level thread group.
*/
ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
- t = new ManagedLocalsThread(rootTG,
- TempFileDeletionHook::runHooks);
+ t = new Thread(rootTG, TempFileDeletionHook::runHooks,
+ "TempFontFileDeleter", 0, false);
/* Set context class loader to null in order to avoid
* keeping a strong reference to an application classloader.
*/
--- a/jdk/src/java.desktop/share/classes/sun/font/FontUtilities.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/font/FontUtilities.java Thu Apr 21 13:37:31 2016 -0700
@@ -183,6 +183,25 @@
}
/**
+ * Return true if there any characters which would trigger layout.
+ * This method considers supplementary characters to be simple,
+ * since we do not presently invoke layout on any code points in
+ * outside the BMP.
+ */
+ public static boolean isComplexScript(char [] chs, int start, int limit) {
+
+ for (int i = start; i < limit; i++) {
+ if (chs[i] < MIN_LAYOUT_CHARCODE) {
+ continue;
+ }
+ else if (isComplexCharCode(chs[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
* If there is anything in the text which triggers a case
* where char->glyph does not map 1:1 in straightforward
* left->right ordering, then this method returns true.
--- a/jdk/src/java.desktop/share/classes/sun/font/SunFontManager.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/font/SunFontManager.java Thu Apr 21 13:37:31 2016 -0700
@@ -55,7 +55,6 @@
import sun.awt.SunToolkit;
import sun.awt.util.ThreadGroupUtils;
import sun.java2d.FontSupport;
-import sun.misc.ManagedLocalsThread;
import sun.util.logging.PlatformLogger;
/**
@@ -2513,8 +2512,8 @@
};
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
- fileCloser = new ManagedLocalsThread(rootTG,
- fileCloserRunnable);
+ fileCloser = new Thread(rootTG, fileCloserRunnable,
+ "FileCloser", 0, false);
fileCloser.setContextClassLoader(null);
Runtime.getRuntime().addShutdownHook(fileCloser);
return null;
--- a/jdk/src/java.desktop/share/classes/sun/java2d/Disposer.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/java2d/Disposer.java Thu Apr 21 13:37:31 2016 -0700
@@ -26,7 +26,6 @@
package sun.java2d;
import sun.awt.util.ThreadGroupUtils;
-import sun.misc.ManagedLocalsThread;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
@@ -85,7 +84,7 @@
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
String name = "Java2D Disposer";
ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
- Thread t = new ManagedLocalsThread(rootTG, disposerInstance, name);
+ Thread t = new Thread(rootTG, disposerInstance, name, 0, false);
t.setContextClassLoader(null);
t.setDaemon(true);
t.setPriority(Thread.MAX_PRIORITY);
--- a/jdk/src/java.desktop/share/classes/sun/java2d/loops/GraphicsPrimitive.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/java2d/loops/GraphicsPrimitive.java Thu Apr 21 13:37:31 2016 -0700
@@ -48,7 +48,6 @@
import java.security.AccessController;
import java.security.PrivilegedAction;
-import sun.misc.ManagedLocalsThread;
import sun.security.action.GetPropertyAction;
/**
@@ -420,8 +419,9 @@
public static void setShutdownHook() {
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
TraceReporter t = new TraceReporter();
- Thread thread = new ManagedLocalsThread(
- ThreadGroupUtils.getRootThreadGroup(), t);
+ Thread thread = new Thread(
+ ThreadGroupUtils.getRootThreadGroup(), t,
+ "TraceReporter", 0, false);
thread.setContextClassLoader(null);
Runtime.getRuntime().addShutdownHook(thread);
return null;
--- a/jdk/src/java.desktop/share/classes/sun/java2d/opengl/OGLRenderQueue.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/java2d/opengl/OGLRenderQueue.java Thu Apr 21 13:37:31 2016 -0700
@@ -28,7 +28,6 @@
import sun.awt.util.ThreadGroupUtils;
import sun.java2d.pipe.RenderBuffer;
import sun.java2d.pipe.RenderQueue;
-import sun.misc.ManagedLocalsThread;
import static sun.java2d.pipe.BufferedOpCodes.*;
import java.security.AccessController;
@@ -161,7 +160,8 @@
public QueueFlusher() {
String name = "Java2D Queue Flusher";
- thread = new ManagedLocalsThread(ThreadGroupUtils.getRootThreadGroup(), this, name);
+ thread = new Thread(ThreadGroupUtils.getRootThreadGroup(),
+ this, name, 0, false);
thread.setDaemon(true);
thread.setPriority(Thread.MAX_PRIORITY);
thread.start();
--- a/jdk/src/java.desktop/share/classes/sun/print/PrintJob2D.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/print/PrintJob2D.java Thu Apr 21 13:37:31 2016 -0700
@@ -71,7 +71,6 @@
import javax.print.attribute.standard.MediaSizeName;
import javax.print.attribute.standard.PageRanges;
-import sun.misc.ManagedLocalsThread;
import sun.print.SunPageSelection;
import sun.print.SunMinMaxPage;
@@ -483,8 +482,30 @@
pageFormat.setOrientation(PageFormat.LANDSCAPE);
} else {
pageFormat.setOrientation(PageFormat.PORTRAIT);
+ }
+
+ PageRanges pageRangesAttr
+ = (PageRanges) attributes.get(PageRanges.class);
+ if (pageRangesAttr != null) {
+ // Get the PageRanges from print dialog.
+ int[][] range = pageRangesAttr.getMembers();
+
+ int prevFromPage = this.jobAttributes.getFromPage();
+ int prevToPage = this.jobAttributes.getToPage();
+
+ int currFromPage = range[0][0];
+ int currToPage = range[range.length - 1][1];
+
+ // if from < to update fromPage first followed by toPage
+ // else update toPage first followed by fromPage
+ if (currFromPage < prevToPage) {
+ this.jobAttributes.setFromPage(currFromPage);
+ this.jobAttributes.setToPage(currToPage);
+ } else {
+ this.jobAttributes.setToPage(currToPage);
+ this.jobAttributes.setFromPage(currFromPage);
}
-
+ }
printerJob.setPrintable(this, pageFormat);
}
@@ -987,7 +1008,8 @@
}
private void startPrinterJobThread() {
- printerJobThread = new ManagedLocalsThread(this, "printerJobThread");
+ printerJobThread =
+ new Thread(null, this, "printerJobThread", 0, false);
printerJobThread.start();
}
--- a/jdk/src/java.desktop/share/classes/sun/print/ServiceNotifier.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/print/ServiceNotifier.java Thu Apr 21 13:37:31 2016 -0700
@@ -25,8 +25,6 @@
package sun.print;
-import sun.misc.ManagedLocalsThread;
-
import java.util.Vector;
import javax.print.PrintService;
@@ -42,15 +40,19 @@
* to obtain the state of the attributes and notifies the listeners of
* any changes.
*/
-class ServiceNotifier extends ManagedLocalsThread {
+class ServiceNotifier extends Thread {
private PrintService service;
private Vector<PrintServiceAttributeListener> listeners;
private boolean stop = false;
private PrintServiceAttributeSet lastSet;
+ /*
+ * If adding any other constructors, always call the 5-args
+ * super-class constructor passing "false" for inherit-locals.
+ */
ServiceNotifier(PrintService service) {
- super(service.getName() + " notifier");
+ super(null, null, service.getName() + " notifier", 0, false);
this.service = service;
listeners = new Vector<>();
try {
@@ -70,7 +72,7 @@
}
}
- void removeListener(PrintServiceAttributeListener listener) {
+ void removeListener(PrintServiceAttributeListener listener) {
synchronized (this) {
if (listener == null || listeners == null) {
return;
--- a/jdk/src/java.desktop/share/classes/sun/swing/plaf/synth/DefaultSynthStyle.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/swing/plaf/synth/DefaultSynthStyle.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, 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
@@ -645,16 +645,7 @@
// StateInfo match, otherwise a StateInfo with
// SELECTED | ENABLED would match ENABLED, which we
// don't want.
-
- // This comes from BigInteger.bitCnt
- int bitCount = oState;
- bitCount -= (0xaaaaaaaa & bitCount) >>> 1;
- bitCount = (bitCount & 0x33333333) + ((bitCount >>> 2) &
- 0x33333333);
- bitCount = bitCount + (bitCount >>> 4) & 0x0f0f0f0f;
- bitCount += bitCount >>> 8;
- bitCount += bitCount >>> 16;
- bitCount = bitCount & 0xff;
+ int bitCount = Integer.bitCount(oState);
if (bitCount > bestCount) {
bestIndex = counter;
bestCount = bitCount;
@@ -883,21 +874,6 @@
}
/**
- * Returns the number of states that are similar between the
- * ComponentState this StateInfo represents and val.
- */
- private int getMatchCount(int val) {
- // This comes from BigInteger.bitCnt
- val &= state;
- val -= (0xaaaaaaaa & val) >>> 1;
- val = (val & 0x33333333) + ((val >>> 2) & 0x33333333);
- val = val + (val >>> 4) & 0x0f0f0f0f;
- val += val >>> 8;
- val += val >>> 16;
- return val & 0xff;
- }
-
- /**
* Creates and returns a copy of this StateInfo.
*
* @return Copy of this StateInfo.
--- a/jdk/src/java.desktop/share/native/libfontmanager/layout/DeviceTables.cpp Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/DeviceTables.cpp Thu Apr 21 13:37:31 2016 -0700
@@ -45,9 +45,12 @@
le_int16 DeviceTable::getAdjustment(const LEReferenceTo<DeviceTable>&base, le_uint16 ppem, LEErrorCode &success) const
{
+ le_int16 result = 0;
+ if (LE_FAILURE(success)) {
+ return result;
+ }
le_uint16 start = SWAPW(startSize);
le_uint16 format = SWAPW(deltaFormat) - 1;
- le_int16 result = 0;
if (ppem >= start && ppem <= SWAPW(endSize) && format < FORMAT_COUNT) {
le_uint16 sizeIndex = ppem - start;
--- a/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstProc.cpp Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstProc.cpp Thu Apr 21 13:37:31 2016 -0700
@@ -71,6 +71,10 @@
{
LEErrorCode success = LE_NO_ERROR;
const LigatureSubstitutionStateEntry *entry = entryTable.getAlias(index, success);
+ if (LE_FAILURE(success)) {
+ currGlyph++;
+ return 0;
+ }
ByteOffset newState = SWAPW(entry->newStateOffset);
le_uint16 flags = SWAPW(entry->flags);
@@ -91,6 +95,10 @@
if (actionOffset != 0) {
LEReferenceTo<LigatureActionEntry> ap(stHeader, success, actionOffset);
+ if (LE_FAILURE(success)) {
+ currGlyph++;
+ return newState;
+ }
LigatureActionEntry action;
le_int32 offset, i = 0, j = 0;
le_int32 stack[nComponents];
@@ -101,6 +109,10 @@
if (j++ > 0) {
ap.addObject(success);
+ if (LE_FAILURE(success)) {
+ currGlyph++;
+ return newState;
+ }
}
action = SWAPL(*ap.getAlias());
@@ -124,9 +136,17 @@
return newState; // get out! bad font
}
i += SWAPW(offsetTable.getObject(LE_GET_GLYPH(glyphStorage[componentGlyph]), success));
+ if (LE_FAILURE(success)) {
+ currGlyph++;
+ return newState;
+ }
if (action & (lafLast | lafStore)) {
LEReferenceTo<TTGlyphID> ligatureOffset(stHeader, success, i);
+ if (LE_FAILURE(success)) {
+ currGlyph++;
+ return newState;
+ }
TTGlyphID ligatureGlyph = SWAPW(*ligatureOffset.getAlias());
glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], ligatureGlyph);
--- a/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstProc2.cpp Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstProc2.cpp Thu Apr 21 13:37:31 2016 -0700
@@ -95,6 +95,10 @@
if (actionOffset != 0) {
LEReferenceTo<LigatureActionEntry> ap(stHeader, success, ligActionOffset); // byte offset
+ if (LE_FAILURE(success)) {
+ currGlyph+= dir;
+ return nextStateIndex;
+ }
ap.addObject(ligActionIndex, success);
LEReferenceToArrayOf<TTGlyphID> ligatureTable(stHeader, success, ligatureOffset, LE_UNBOUNDED_ARRAY);
LigatureActionEntry action;
@@ -104,8 +108,8 @@
LEReferenceToArrayOf<le_uint16> componentTable(stHeader, success, componentOffset, LE_UNBOUNDED_ARRAY);
if(LE_FAILURE(success)) {
- currGlyph+= dir;
- return nextStateIndex; // get out! bad font
+ currGlyph+= dir;
+ return nextStateIndex; // get out! bad font
}
do {
@@ -114,6 +118,10 @@
if (j++ > 0) {
ap.addObject(success);
}
+ if (LE_FAILURE(success)) {
+ currGlyph+= dir;
+ return nextStateIndex;
+ }
action = SWAPL(*ap.getAlias());
@@ -129,9 +137,17 @@
return nextStateIndex; // get out! bad font
}
i += SWAPW(componentTable(LE_GET_GLYPH(glyphStorage[componentGlyph]) + (SignExtend(offset, lafComponentOffsetMask)),success));
+ if (LE_FAILURE(success)) {
+ currGlyph+= dir;
+ return nextStateIndex;
+ }
if (action & (lafLast | lafStore)) {
TTGlyphID ligatureGlyph = SWAPW(ligatureTable(i,success));
+ if (LE_FAILURE(success)) {
+ currGlyph+= dir;
+ return nextStateIndex;
+ }
glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], ligatureGlyph);
if(mm==nComponents) {
LE_DEBUG_BAD_FONT("exceeded nComponents");
--- a/jdk/src/java.desktop/share/native/libfontmanager/layout/StateTableProcessor2.cpp Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/StateTableProcessor2.cpp Thu Apr 21 13:37:31 2016 -0700
@@ -60,6 +60,7 @@
entryTableOffset = SWAPL(stHeader->entryTableOffset);
classTable = LEReferenceTo<LookupTable>(stHeader, success, classTableOffset);
+ if (LE_FAILURE(success)) return;
format = SWAPW(classTable->format);
stateArray = LEReferenceToArrayOf<EntryTableIndex2>(stHeader, success, stateArrayOffset, LE_UNBOUNDED_ARRAY);
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/GtkFileDialogPeer.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/GtkFileDialogPeer.java Thu Apr 21 13:37:31 2016 -0700
@@ -29,7 +29,6 @@
import java.io.File;
import java.io.FilenameFilter;
import sun.awt.AWTAccessor;
-import sun.misc.ManagedLocalsThread;
/**
* FileDialogPeer for the GtkFileChooser.
@@ -120,7 +119,7 @@
standaloneWindow = 0;
fd.setVisible(false);
};
- new ManagedLocalsThread(task).start();
+ new Thread(null, task, "ShowDialog", 0, false).start();
} else {
quit();
fd.setVisible(false);
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/InfoWindow.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/InfoWindow.java Thu Apr 21 13:37:31 2016 -0700
@@ -29,7 +29,6 @@
import java.awt.event.*;
import java.awt.peer.TrayIconPeer;
import sun.awt.*;
-import sun.misc.ManagedLocalsThread;
import java.awt.image.*;
import java.text.BreakIterator;
@@ -452,7 +451,7 @@
final Thread thread;
Displayer() {
- this.thread = new ManagedLocalsThread(this);
+ this.thread = new Thread(null, this, "Displayer", 0, false);
this.thread.setDaemon(true);
}
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XBaseMenuWindow.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XBaseMenuWindow.java Thu Apr 21 13:37:31 2016 -0700
@@ -1087,7 +1087,7 @@
}
} else {
//Invoke action event
- item.action(mouseEvent.getWhen());
+ item.action(mouseEvent.getWhen(), mouseEvent.getModifiers());
ungrabInput();
}
} else {
@@ -1200,7 +1200,7 @@
if (citem instanceof XMenuPeer) {
cwnd.selectItem(citem, true);
} else if (citem != null) {
- citem.action(event.getWhen());
+ citem.action(event.getWhen(), event.getModifiers());
ungrabInput();
}
break;
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuItemPeer.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuItemPeer.java Thu Apr 21 13:37:31 2016 -0700
@@ -323,11 +323,11 @@
* on menu item.
* @param when the timestamp of action event
*/
- void action(long when) {
+ void action(long when, int modifiers) {
if (!isSeparator() && isTargetItemEnabled()) {
XWindow.postEventStatic(new ActionEvent(target, ActionEvent.ACTION_PERFORMED,
getTargetActionCommand(), when,
- 0));
+ modifiers));
}
}
/************************************************
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTaskbarPeer.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTaskbarPeer.java Thu Apr 21 13:37:31 2016 -0700
@@ -29,7 +29,6 @@
import java.awt.Taskbar.Feature;
import java.awt.peer.TaskbarPeer;
import java.awt.event.ActionEvent;
-import sun.misc.ManagedLocalsThread;
import java.security.AccessController;
import sun.security.action.GetPropertyAction;
@@ -48,10 +47,8 @@
new GetPropertyAction("java.desktop.appName", ""));
nativeLibraryLoaded = init(dname);
if (nativeLibraryLoaded) {
- ManagedLocalsThread t
- = new ManagedLocalsThread(() -> {
- runloop();
- });
+ Thread t = new Thread(null, () -> { runloop(); },
+ "TaskBar", 0, false);
t.setDaemon(true);
t.start();
}
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java Thu Apr 21 13:37:31 2016 -0700
@@ -284,8 +284,8 @@
}
};
String name = "XToolkt-Shutdown-Thread";
- Thread shutdownThread = new ManagedLocalsThread(
- ThreadGroupUtils.getRootThreadGroup(), r, name);
+ Thread shutdownThread = new Thread(
+ ThreadGroupUtils.getRootThreadGroup(), r, name, 0, false);
shutdownThread.setContextClassLoader(null);
Runtime.getRuntime().addShutdownHook(shutdownThread);
return null;
@@ -332,8 +332,9 @@
toolkitThread = AccessController.doPrivileged((PrivilegedAction<Thread>) () -> {
String name = "AWT-XAWT";
- Thread thread = new ManagedLocalsThread(
- ThreadGroupUtils.getRootThreadGroup(), this, name);
+ Thread thread = new Thread(
+ ThreadGroupUtils.getRootThreadGroup(), this, name,
+ 0, false);
thread.setContextClassLoader(null);
thread.setPriority(Thread.NORM_PRIORITY + 1);
thread.setDaemon(true);
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java Thu Apr 21 13:37:31 2016 -0700
@@ -44,7 +44,6 @@
import sun.awt.util.ThreadGroupUtils;
import sun.java2d.SunGraphicsEnvironment;
-import sun.misc.ManagedLocalsThread;
/**
* This is an implementation of a GraphicsDevice object for a single
@@ -442,8 +441,8 @@
}
};
String name = "Display-Change-Shutdown-Thread-" + screen;
- Thread t = new ManagedLocalsThread(
- ThreadGroupUtils.getRootThreadGroup(), r, name);
+ Thread t = new Thread(
+ ThreadGroupUtils.getRootThreadGroup(), r, name, 0, false);
t.setContextClassLoader(null);
Runtime.getRuntime().addShutdownHook(t);
return null;
--- a/jdk/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java Thu Apr 21 13:37:31 2016 -0700
@@ -25,8 +25,6 @@
package sun.print;
-import sun.misc.ManagedLocalsThread;
-
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
@@ -213,7 +211,8 @@
public PrintServiceLookupProvider() {
// start the printer listener thread
if (pollServices) {
- Thread thr = new ManagedLocalsThread(new PrinterChangeListener());
+ Thread thr = new Thread(null, new PrinterChangeListener(),
+ "PrinterListener", 0, false);
thr.setDaemon(true);
thr.start();
IPPPrintService.debug_println(debugPrefix+"polling turned on");
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -1877,31 +1877,34 @@
AWT_LOCK();
- config = awt_XRRGetScreenInfo(awt_display,
- RootWindow(awt_display, screen));
- if (config != NULL) {
- Rotation rotation;
- short curRate;
- SizeID curSizeIndex;
- XRRScreenSize *sizes;
- int nsizes;
+ if (screen < ScreenCount(awt_display)) {
- curSizeIndex = awt_XRRConfigCurrentConfiguration(config, &rotation);
- sizes = awt_XRRConfigSizes(config, &nsizes);
- curRate = awt_XRRConfigCurrentRate(config);
+ config = awt_XRRGetScreenInfo(awt_display,
+ RootWindow(awt_display, screen));
+ if (config != NULL) {
+ Rotation rotation;
+ short curRate;
+ SizeID curSizeIndex;
+ XRRScreenSize *sizes;
+ int nsizes;
- if ((sizes != NULL) &&
- (curSizeIndex < nsizes))
- {
- XRRScreenSize curSize = sizes[curSizeIndex];
- displayMode = X11GD_CreateDisplayMode(env,
- curSize.width,
- curSize.height,
- BIT_DEPTH_MULTI,
- curRate);
+ curSizeIndex = awt_XRRConfigCurrentConfiguration(config, &rotation);
+ sizes = awt_XRRConfigSizes(config, &nsizes);
+ curRate = awt_XRRConfigCurrentRate(config);
+
+ if ((sizes != NULL) &&
+ (curSizeIndex < nsizes))
+ {
+ XRRScreenSize curSize = sizes[curSizeIndex];
+ displayMode = X11GD_CreateDisplayMode(env,
+ curSize.width,
+ curSize.height,
+ BIT_DEPTH_MULTI,
+ curRate);
+ }
+
+ awt_XRRFreeScreenConfigInfo(config);
}
-
- awt_XRRFreeScreenConfigInfo(config);
}
AWT_FLUSH_UNLOCK();
--- a/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java Thu Apr 21 13:37:31 2016 -0700
@@ -41,7 +41,6 @@
import static sun.awt.shell.Win32ShellFolder2.*;
import sun.awt.OSInfo;
import sun.awt.util.ThreadGroupUtils;
-import sun.misc.ManagedLocalsThread;
// NOTE: This class supersedes Win32ShellFolderManager, which was removed
// from distribution after version 1.4.2.
@@ -524,8 +523,9 @@
return null;
});
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
- Thread t = new ManagedLocalsThread(
- ThreadGroupUtils.getRootThreadGroup(), shutdownHook);
+ Thread t = new Thread(
+ ThreadGroupUtils.getRootThreadGroup(), shutdownHook,
+ "ShellFolder", 0, false);
Runtime.getRuntime().addShutdownHook(t);
return null;
});
@@ -548,8 +548,9 @@
* which will not get GCed before VM exit.
* Make its parent the top-level thread group.
*/
- Thread thread = new ManagedLocalsThread(
- ThreadGroupUtils.getRootThreadGroup(), comRun, name);
+ Thread thread = new Thread(
+ ThreadGroupUtils.getRootThreadGroup(), comRun, name,
+ 0, false);
thread.setDaemon(true);
return thread;
});
--- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WFileDialogPeer.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WFileDialogPeer.java Thu Apr 21 13:37:31 2016 -0700
@@ -36,7 +36,6 @@
import java.util.Vector;
import sun.awt.CausedFocusEvent;
import sun.awt.AWTAccessor;
-import sun.misc.ManagedLocalsThread;
final class WFileDialogPeer extends WWindowPeer implements FileDialogPeer {
@@ -98,7 +97,7 @@
@Override
public void show() {
- new ManagedLocalsThread(this::_show).start();
+ new Thread(null, this::_show, "FileDialog", 0, false).start();
}
@Override
--- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPageDialogPeer.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPageDialogPeer.java Thu Apr 21 13:37:31 2016 -0700
@@ -25,8 +25,6 @@
package sun.awt.windows;
-import sun.misc.ManagedLocalsThread;
-
final class WPageDialogPeer extends WPrintDialogPeer {
WPageDialogPeer(WPageDialog target) {
@@ -53,6 +51,6 @@
}
((WPrintDialog)target).setVisible(false);
};
- new ManagedLocalsThread(runnable).start();
+ new Thread(null, runnable, "PageDialog", 0, false).start();
}
}
--- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrintDialogPeer.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrintDialogPeer.java Thu Apr 21 13:37:31 2016 -0700
@@ -32,7 +32,6 @@
import java.util.Vector;
import sun.awt.CausedFocusEvent;
import sun.awt.AWTAccessor;
-import sun.misc.ManagedLocalsThread;
class WPrintDialogPeer extends WWindowPeer implements DialogPeer {
@@ -78,7 +77,7 @@
}
((WPrintDialog)target).setVisible(false);
};
- new ManagedLocalsThread(runnable).start();
+ new Thread(null, runnable, "PrintDialog", 0, false).start();
}
synchronized void setHWnd(long hwnd) {
--- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java Thu Apr 21 13:37:31 2016 -0700
@@ -52,7 +52,6 @@
import sun.java2d.d3d.D3DRenderQueue;
import sun.java2d.opengl.OGLRenderQueue;
-import sun.misc.ManagedLocalsThread;
import sun.print.PrintJob2D;
import java.awt.dnd.DragSource;
@@ -256,7 +255,7 @@
(PrivilegedAction<ThreadGroup>) ThreadGroupUtils::getRootThreadGroup);
if (!startToolkitThread(this, rootTG)) {
String name = "AWT-Windows";
- Thread toolkitThread = new ManagedLocalsThread(rootTG, this, name);
+ Thread toolkitThread = new Thread(rootTG, this, name, 0, false);
toolkitThread.setDaemon(true);
toolkitThread.start();
}
@@ -283,8 +282,9 @@
private void registerShutdownHook() {
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
- Thread shutdown = new ManagedLocalsThread(
- ThreadGroupUtils.getRootThreadGroup(), this::shutdown);
+ Thread shutdown = new Thread(
+ ThreadGroupUtils.getRootThreadGroup(), this::shutdown,
+ "ToolkitShutdown", 0, false);
shutdown.setContextClassLoader(null);
Runtime.getRuntime().addShutdownHook(shutdown);
return null;
--- a/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java Thu Apr 21 13:37:31 2016 -0700
@@ -49,7 +49,6 @@
import sun.java2d.windows.GDIWindowSurfaceData;
import sun.java2d.d3d.D3DSurfaceData.D3DWindowSurfaceData;
import sun.java2d.windows.WindowsFlags;
-import sun.misc.ManagedLocalsThread;
/**
* This class handles rendering to the screen with the D3D pipeline.
@@ -99,8 +98,9 @@
done = true;
wakeUpUpdateThread();
};
- Thread shutdown = new ManagedLocalsThread(
- ThreadGroupUtils.getRootThreadGroup(), shutdownRunnable);
+ Thread shutdown = new Thread(
+ ThreadGroupUtils.getRootThreadGroup(), shutdownRunnable,
+ "ScreenUpdater", 0, false);
shutdown.setContextClassLoader(null);
try {
Runtime.getRuntime().addShutdownHook(shutdown);
@@ -348,8 +348,9 @@
if (screenUpdater == null) {
screenUpdater = AccessController.doPrivileged((PrivilegedAction<Thread>) () -> {
String name = "D3D Screen Updater";
- Thread t = new ManagedLocalsThread(
- ThreadGroupUtils.getRootThreadGroup(), this, name);
+ Thread t = new Thread(
+ ThreadGroupUtils.getRootThreadGroup(), this, name,
+ 0, false);
// REMIND: should it be higher?
t.setPriority(Thread.NORM_PRIORITY + 2);
t.setDaemon(true);
--- a/jdk/src/java.desktop/windows/classes/sun/print/PrintServiceLookupProvider.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/windows/classes/sun/print/PrintServiceLookupProvider.java Thu Apr 21 13:37:31 2016 -0700
@@ -25,8 +25,6 @@
package sun.print;
-import sun.misc.ManagedLocalsThread;
-
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -99,7 +97,8 @@
return;
}
// start the printer listener thread
- Thread thr = new ManagedLocalsThread(new PrinterChangeListener());
+ Thread thr = new Thread(null, new PrinterChangeListener(),
+ "PrinterListener", 0, false);
thr.setDaemon(true);
thr.start();
} /* else condition ought to never happen! */
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Button.cpp Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Button.cpp Thu Apr 21 13:37:31 2016 -0700
@@ -187,7 +187,7 @@
AwtButton::NotifyListeners()
{
DoCallback("handleAction", "(JI)V", ::JVM_CurrentTimeMillis(NULL, 0),
- (jint)AwtComponent::GetJavaModifiers());
+ (jint)AwtComponent::GetActionModifiers());
}
MsgRouting
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp Thu Apr 21 13:37:31 2016 -0700
@@ -60,6 +60,7 @@
#include <java_awt_Insets.h>
#include <sun_awt_windows_WPanelPeer.h>
#include <java_awt_event_InputEvent.h>
+#include <java_awt_event_ActionEvent.h>
#include <java_awt_event_InputMethodEvent.h>
#include <sun_awt_windows_WInputMethod.h>
#include <java_awt_event_MouseEvent.h>
@@ -2587,6 +2588,27 @@
return java_awt_event_KeyEvent_KEY_LOCATION_LEFT;
}
+/* Returns Java ActionEvent modifieres.
+ * When creating ActionEvent, modifiers provided by ActionEvent
+ * class should be set.
+ */
+jint
+AwtComponent::GetActionModifiers()
+{
+ jint modifiers = GetJavaModifiers();
+
+ if (modifiers & java_awt_event_InputEvent_CTRL_DOWN_MASK) {
+ modifiers |= java_awt_event_ActionEvent_CTRL_MASK;
+ }
+ if (modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK) {
+ modifiers |= java_awt_event_ActionEvent_SHIFT_MASK;
+ }
+ if (modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK) {
+ modifiers |= java_awt_event_ActionEvent_ALT_MASK;
+ }
+ return modifiers;
+}
+
/* Returns Java extended InputEvent modifieres.
* Since ::GetKeyState returns current state and Java modifiers represent
* state before event, modifier on changed key are inverted.
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.h Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.h Thu Apr 21 13:37:31 2016 -0700
@@ -438,6 +438,7 @@
static void InitDynamicKeyMapTable();
static void BuildDynamicKeyMapTable();
static jint GetJavaModifiers();
+ static jint GetActionModifiers();
static jint GetButton(int mouseButton);
static UINT GetButtonMK(int mouseButton);
static UINT WindowsKeyToJavaKey(UINT windowsKey, UINT modifiers, UINT character, BOOL isDeadKey);
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_List.cpp Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_List.cpp Thu Apr 21 13:37:31 2016 -0700
@@ -536,7 +536,7 @@
else if (notifyCode == LBN_DBLCLK) {
DoCallback("handleAction", "(IJI)V", nCurrentSelection,
::JVM_CurrentTimeMillis(NULL, 0),
- (jint)AwtComponent::GetJavaModifiers());
+ (jint)AwtComponent::GetActionModifiers());
}
}
}
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_List.h Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_List.h Thu Apr 21 13:37:31 2016 -0700
@@ -56,6 +56,7 @@
}
INLINE void Deselect(int pos) {
if (isMultiSelect) {
+ SendListMessage(LB_SETCARETINDEX, pos, FALSE);
SendListMessage(LB_SETSEL, FALSE, pos);
}
else {
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_MenuItem.cpp Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_MenuItem.cpp Thu Apr 21 13:37:31 2016 -0700
@@ -667,7 +667,7 @@
DoCallback("handleAction", "(Z)V", ((nState & MF_CHECKED) == 0));
} else {
DoCallback("handleAction", "(JI)V", ::JVM_CurrentTimeMillis(NULL, 0),
- (jint)AwtComponent::GetJavaModifiers());
+ (jint)AwtComponent::GetActionModifiers());
}
}
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_TrayIcon.cpp Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_TrayIcon.cpp Thu Apr 21 13:37:31 2016 -0700
@@ -409,7 +409,7 @@
MSG msg;
AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
SendActionEvent(java_awt_event_ActionEvent_ACTION_PERFORMED, ::JVM_CurrentTimeMillis(NULL, 0),
- AwtComponent::GetJavaModifiers(), &msg);
+ AwtComponent::GetActionModifiers(), &msg);
}
return mrConsume;
}
@@ -425,7 +425,7 @@
MSG msg;
AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
SendActionEvent(java_awt_event_ActionEvent_ACTION_PERFORMED, ::JVM_CurrentTimeMillis(NULL, 0),
- AwtComponent::GetJavaModifiers(), &msg);
+ AwtComponent::GetActionModifiers(), &msg);
}
lastKeySelectTime = now;
@@ -442,7 +442,7 @@
MSG msg;
AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
SendActionEvent(java_awt_event_ActionEvent_ACTION_PERFORMED, ::JVM_CurrentTimeMillis(NULL, 0),
- AwtComponent::GetJavaModifiers(), &msg);
+ AwtComponent::GetActionModifiers(), &msg);
}
return mrConsume;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/BinaryRepresentationWriter.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015, 2016, 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.net.httpclient.hpack;
+
+import java.nio.ByteBuffer;
+
+interface BinaryRepresentationWriter {
+
+ boolean write(HeaderTable table, ByteBuffer destination);
+
+ BinaryRepresentationWriter reset();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/BulkSizeUpdateWriter.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2016, 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.net.httpclient.hpack;
+
+import java.nio.ByteBuffer;
+import java.util.Iterator;
+
+import static java.util.Objects.requireNonNull;
+
+final class BulkSizeUpdateWriter implements BinaryRepresentationWriter {
+
+ private final SizeUpdateWriter writer = new SizeUpdateWriter();
+ private Iterator<Integer> maxSizes;
+ private boolean writing;
+ private boolean configured;
+
+ BulkSizeUpdateWriter maxHeaderTableSizes(Iterable<Integer> sizes) {
+ if (configured) {
+ throw new IllegalStateException("Already configured");
+ }
+ requireNonNull(sizes, "sizes");
+ maxSizes = sizes.iterator();
+ configured = true;
+ return this;
+ }
+
+ @Override
+ public boolean write(HeaderTable table, ByteBuffer destination) {
+ if (!configured) {
+ throw new IllegalStateException("Configure first");
+ }
+ while (true) {
+ if (writing) {
+ if (!writer.write(table, destination)) {
+ return false;
+ }
+ writing = false;
+ } else if (maxSizes.hasNext()) {
+ writing = true;
+ writer.reset();
+ writer.maxHeaderTableSize(maxSizes.next());
+ } else {
+ configured = false;
+ return true;
+ }
+ }
+ }
+
+ @Override
+ public BulkSizeUpdateWriter reset() {
+ maxSizes = null;
+ writing = false;
+ configured = false;
+ return this;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/Decoder.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,506 @@
+/*
+ * Copyright (c) 2014, 2016, 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.net.httpclient.hpack;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.net.ProtocolException;
+import java.nio.ByteBuffer;
+
+import static java.lang.String.format;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Decodes headers from their binary representation.
+ *
+ * <p>Typical lifecycle looks like this:
+ *
+ * <p> {@link #Decoder(int) new Decoder}
+ * ({@link #setMaxCapacity(int) setMaxCapacity}?
+ * {@link #decode(ByteBuffer, boolean, DecodingCallback) decode})*
+ *
+ * @apiNote
+ *
+ * <p> The design intentions behind Decoder were to facilitate flexible and
+ * incremental style of processing.
+ *
+ * <p> {@code Decoder} does not require a complete header block in a single
+ * {@code ByteBuffer}. The header block can be spread across many buffers of any
+ * size and decoded one-by-one the way it makes most sense for the user. This
+ * way also allows not to limit the size of the header block.
+ *
+ * <p> Headers are delivered to the {@linkplain DecodingCallback callback} as
+ * soon as they become decoded. Using the callback also gives the user a freedom
+ * to decide how headers are processed. The callback does not limit the number
+ * of headers decoded during single decoding operation.
+ *
+ * @since 9
+ */
+public final class Decoder {
+
+ private static final State[] states = new State[256];
+
+ static {
+ // To be able to do a quick lookup, each of 256 possibilities are mapped
+ // to corresponding states.
+ //
+ // We can safely do this since patterns 1, 01, 001, 0001, 0000 are
+ // Huffman prefixes and therefore are inherently not ambiguous.
+ //
+ // I do it mainly for better debugging (to not go each time step by step
+ // through if...else tree). As for performance win for the decoding, I
+ // believe is negligible.
+ for (int i = 0; i < states.length; i++) {
+ if ((i & 0b1000_0000) == 0b1000_0000) {
+ states[i] = State.INDEXED;
+ } else if ((i & 0b1100_0000) == 0b0100_0000) {
+ states[i] = State.LITERAL_WITH_INDEXING;
+ } else if ((i & 0b1110_0000) == 0b0010_0000) {
+ states[i] = State.SIZE_UPDATE;
+ } else if ((i & 0b1111_0000) == 0b0001_0000) {
+ states[i] = State.LITERAL_NEVER_INDEXED;
+ } else if ((i & 0b1111_0000) == 0b0000_0000) {
+ states[i] = State.LITERAL;
+ } else {
+ throw new InternalError(String.valueOf(i));
+ }
+ }
+ }
+
+ private final HeaderTable table;
+
+ private State state = State.READY;
+ private final IntegerReader integerReader;
+ private final StringReader stringReader;
+ private final StringBuilder name;
+ private final StringBuilder value;
+ private int intValue;
+ private boolean firstValueRead;
+ private boolean firstValueIndex;
+ private boolean nameHuffmanEncoded;
+ private boolean valueHuffmanEncoded;
+ private int capacity;
+
+ /**
+ * Constructs a {@code Decoder} with the specified initial capacity of the
+ * header table.
+ *
+ * <p> The value has to be agreed between decoder and encoder out-of-band,
+ * e.g. by a protocol that uses HPACK (see <a
+ * href="https://tools.ietf.org/html/rfc7541#section-4.2">4.2. Maximum Table
+ * Size</a>).
+ *
+ * @param capacity
+ * a non-negative integer
+ *
+ * @throws IllegalArgumentException
+ * if capacity is negative
+ */
+ public Decoder(int capacity) {
+ setMaxCapacity(capacity);
+ table = new HeaderTable(capacity);
+ integerReader = new IntegerReader();
+ stringReader = new StringReader();
+ name = new StringBuilder(512);
+ value = new StringBuilder(1024);
+ }
+
+ /**
+ * Sets a maximum capacity of the header table.
+ *
+ * <p> The value has to be agreed between decoder and encoder out-of-band,
+ * e.g. by a protocol that uses HPACK (see <a
+ * href="https://tools.ietf.org/html/rfc7541#section-4.2">4.2. Maximum Table
+ * Size</a>).
+ *
+ * @param capacity
+ * a non-negative integer
+ *
+ * @throws IllegalArgumentException
+ * if capacity is negative
+ */
+ public void setMaxCapacity(int capacity) {
+ if (capacity < 0) {
+ throw new IllegalArgumentException("capacity >= 0: " + capacity);
+ }
+ // FIXME: await capacity update if less than what was prior to it
+ this.capacity = capacity;
+ }
+
+ /**
+ * Decodes a header block from the given buffer to the given callback.
+ *
+ * <p> Suppose a header block is represented by a sequence of {@code
+ * ByteBuffer}s in the form of {@code Iterator<ByteBuffer>}. And the
+ * consumer of decoded headers is represented by the callback. Then to
+ * decode the header block, the following approach might be used:
+ *
+ * <pre>{@code
+ * while (buffers.hasNext()) {
+ * ByteBuffer input = buffers.next();
+ * decoder.decode(input, callback, !buffers.hasNext());
+ * }
+ * }</pre>
+ *
+ * <p> The decoder reads as much as possible of the header block from the
+ * given buffer, starting at the buffer's position, and increments its
+ * position to reflect the bytes read. The buffer's mark and limit will not
+ * be modified.
+ *
+ * <p> Once the method is invoked with {@code endOfHeaderBlock == true}, the
+ * current header block is deemed ended, and inconsistencies, if any, are
+ * reported immediately by throwing an {@code UncheckedIOException}.
+ *
+ * <p> Each callback method is called only after the implementation has
+ * processed the corresponding bytes. If the bytes revealed a decoding
+ * error, the callback method is not called.
+ *
+ * <p> In addition to exceptions thrown directly by the method, any
+ * exceptions thrown from the {@code callback} will bubble up.
+ *
+ * @apiNote The method asks for {@code endOfHeaderBlock} flag instead of
+ * returning it for two reasons. The first one is that the user of the
+ * decoder always knows which chunk is the last. The second one is to throw
+ * the most detailed exception possible, which might be useful for
+ * diagnosing issues.
+ *
+ * @implNote This implementation is not atomic in respect to decoding
+ * errors. In other words, if the decoding operation has thrown a decoding
+ * error, the decoder is no longer usable.
+ *
+ * @param headerBlock
+ * the chunk of the header block, may be empty
+ * @param endOfHeaderBlock
+ * true if the chunk is the final (or the only one) in the sequence
+ *
+ * @param consumer
+ * the callback
+ * @throws UncheckedIOException
+ * in case of a decoding error
+ * @throws NullPointerException
+ * if either headerBlock or consumer are null
+ */
+ public void decode(ByteBuffer headerBlock, boolean endOfHeaderBlock,
+ DecodingCallback consumer) {
+ requireNonNull(headerBlock, "headerBlock");
+ requireNonNull(consumer, "consumer");
+ while (headerBlock.hasRemaining()) {
+ proceed(headerBlock, consumer);
+ }
+ if (endOfHeaderBlock && state != State.READY) {
+ throw new UncheckedIOException(
+ new ProtocolException("Unexpected end of header block"));
+ }
+ }
+
+ private void proceed(ByteBuffer input, DecodingCallback action) {
+ switch (state) {
+ case READY:
+ resumeReady(input);
+ break;
+ case INDEXED:
+ resumeIndexed(input, action);
+ break;
+ case LITERAL:
+ resumeLiteral(input, action);
+ break;
+ case LITERAL_WITH_INDEXING:
+ resumeLiteralWithIndexing(input, action);
+ break;
+ case LITERAL_NEVER_INDEXED:
+ resumeLiteralNeverIndexed(input, action);
+ break;
+ case SIZE_UPDATE:
+ resumeSizeUpdate(input, action);
+ break;
+ default:
+ throw new InternalError(
+ "Unexpected decoder state: " + String.valueOf(state));
+ }
+ }
+
+ private void resumeReady(ByteBuffer input) {
+ int b = input.get(input.position()) & 0xff; // absolute read
+ State s = states[b];
+ switch (s) {
+ case INDEXED:
+ integerReader.configure(7);
+ state = State.INDEXED;
+ firstValueIndex = true;
+ break;
+ case LITERAL:
+ state = State.LITERAL;
+ firstValueIndex = (b & 0b0000_1111) != 0;
+ if (firstValueIndex) {
+ integerReader.configure(4);
+ }
+ break;
+ case LITERAL_WITH_INDEXING:
+ state = State.LITERAL_WITH_INDEXING;
+ firstValueIndex = (b & 0b0011_1111) != 0;
+ if (firstValueIndex) {
+ integerReader.configure(6);
+ }
+ break;
+ case LITERAL_NEVER_INDEXED:
+ state = State.LITERAL_NEVER_INDEXED;
+ firstValueIndex = (b & 0b0000_1111) != 0;
+ if (firstValueIndex) {
+ integerReader.configure(4);
+ }
+ break;
+ case SIZE_UPDATE:
+ integerReader.configure(5);
+ state = State.SIZE_UPDATE;
+ firstValueIndex = true;
+ break;
+ default:
+ throw new InternalError(String.valueOf(s));
+ }
+ if (!firstValueIndex) {
+ input.get(); // advance, next stop: "String Literal"
+ }
+ }
+
+ // 0 1 2 3 4 5 6 7
+ // +---+---+---+---+---+---+---+---+
+ // | 1 | Index (7+) |
+ // +---+---------------------------+
+ //
+ private void resumeIndexed(ByteBuffer input, DecodingCallback action) {
+ if (!integerReader.read(input)) {
+ return;
+ }
+ intValue = integerReader.get();
+ integerReader.reset();
+ try {
+ HeaderTable.HeaderField f = table.get(intValue);
+ action.onIndexed(intValue, f.name, f.value);
+ } finally {
+ state = State.READY;
+ }
+ }
+
+ // 0 1 2 3 4 5 6 7
+ // +---+---+---+---+---+---+---+---+
+ // | 0 | 0 | 0 | 0 | Index (4+) |
+ // +---+---+-----------------------+
+ // | H | Value Length (7+) |
+ // +---+---------------------------+
+ // | Value String (Length octets) |
+ // +-------------------------------+
+ //
+ // 0 1 2 3 4 5 6 7
+ // +---+---+---+---+---+---+---+---+
+ // | 0 | 0 | 0 | 0 | 0 |
+ // +---+---+-----------------------+
+ // | H | Name Length (7+) |
+ // +---+---------------------------+
+ // | Name String (Length octets) |
+ // +---+---------------------------+
+ // | H | Value Length (7+) |
+ // +---+---------------------------+
+ // | Value String (Length octets) |
+ // +-------------------------------+
+ //
+ private void resumeLiteral(ByteBuffer input, DecodingCallback action) {
+ if (!completeReading(input)) {
+ return;
+ }
+ try {
+ if (firstValueIndex) {
+ HeaderTable.HeaderField f = table.get(intValue);
+ action.onLiteral(intValue, f.name, value, valueHuffmanEncoded);
+ } else {
+ action.onLiteral(name, nameHuffmanEncoded, value, valueHuffmanEncoded);
+ }
+ } finally {
+ cleanUpAfterReading();
+ }
+ }
+
+ //
+ // 0 1 2 3 4 5 6 7
+ // +---+---+---+---+---+---+---+---+
+ // | 0 | 1 | Index (6+) |
+ // +---+---+-----------------------+
+ // | H | Value Length (7+) |
+ // +---+---------------------------+
+ // | Value String (Length octets) |
+ // +-------------------------------+
+ //
+ // 0 1 2 3 4 5 6 7
+ // +---+---+---+---+---+---+---+---+
+ // | 0 | 1 | 0 |
+ // +---+---+-----------------------+
+ // | H | Name Length (7+) |
+ // +---+---------------------------+
+ // | Name String (Length octets) |
+ // +---+---------------------------+
+ // | H | Value Length (7+) |
+ // +---+---------------------------+
+ // | Value String (Length octets) |
+ // +-------------------------------+
+ //
+ private void resumeLiteralWithIndexing(ByteBuffer input, DecodingCallback action) {
+ if (!completeReading(input)) {
+ return;
+ }
+ try {
+ //
+ // 1. (name, value) will be stored in the table as strings
+ // 2. Most likely the callback will also create strings from them
+ // ------------------------------------------------------------------------
+ // Let's create those string beforehand (and only once!) to benefit everyone
+ //
+ String n;
+ String v = value.toString();
+ if (firstValueIndex) {
+ HeaderTable.HeaderField f = table.get(intValue);
+ n = f.name;
+ action.onLiteralWithIndexing(intValue, n, v, valueHuffmanEncoded);
+ } else {
+ n = name.toString();
+ action.onLiteralWithIndexing(n, nameHuffmanEncoded, v, valueHuffmanEncoded);
+ }
+ table.put(n, v);
+ } catch (IllegalArgumentException | IllegalStateException e) {
+ throw new UncheckedIOException(
+ (IOException) new ProtocolException().initCause(e));
+ } finally {
+ cleanUpAfterReading();
+ }
+ }
+
+ // 0 1 2 3 4 5 6 7
+ // +---+---+---+---+---+---+---+---+
+ // | 0 | 0 | 0 | 1 | Index (4+) |
+ // +---+---+-----------------------+
+ // | H | Value Length (7+) |
+ // +---+---------------------------+
+ // | Value String (Length octets) |
+ // +-------------------------------+
+ //
+ // 0 1 2 3 4 5 6 7
+ // +---+---+---+---+---+---+---+---+
+ // | 0 | 0 | 0 | 1 | 0 |
+ // +---+---+-----------------------+
+ // | H | Name Length (7+) |
+ // +---+---------------------------+
+ // | Name String (Length octets) |
+ // +---+---------------------------+
+ // | H | Value Length (7+) |
+ // +---+---------------------------+
+ // | Value String (Length octets) |
+ // +-------------------------------+
+ //
+ private void resumeLiteralNeverIndexed(ByteBuffer input, DecodingCallback action) {
+ if (!completeReading(input)) {
+ return;
+ }
+ try {
+ if (firstValueIndex) {
+ HeaderTable.HeaderField f = table.get(intValue);
+ action.onLiteralNeverIndexed(intValue, f.name, value, valueHuffmanEncoded);
+ } else {
+ action.onLiteralNeverIndexed(name, nameHuffmanEncoded, value, valueHuffmanEncoded);
+ }
+ } finally {
+ cleanUpAfterReading();
+ }
+ }
+
+ // 0 1 2 3 4 5 6 7
+ // +---+---+---+---+---+---+---+---+
+ // | 0 | 0 | 1 | Max size (5+) |
+ // +---+---------------------------+
+ //
+ private void resumeSizeUpdate(ByteBuffer input, DecodingCallback action) {
+ if (!integerReader.read(input)) {
+ return;
+ }
+ intValue = integerReader.get();
+ assert intValue >= 0;
+ if (intValue > capacity) {
+ throw new UncheckedIOException(new ProtocolException(
+ format("Received capacity exceeds expected: " +
+ "capacity=%s, expected=%s", intValue, capacity)));
+ }
+ integerReader.reset();
+ try {
+ action.onSizeUpdate(intValue);
+ table.setMaxSize(intValue);
+ } finally {
+ state = State.READY;
+ }
+ }
+
+ private boolean completeReading(ByteBuffer input) {
+ if (!firstValueRead) {
+ if (firstValueIndex) {
+ if (!integerReader.read(input)) {
+ return false;
+ }
+ intValue = integerReader.get();
+ integerReader.reset();
+ } else {
+ if (!stringReader.read(input, name)) {
+ return false;
+ }
+ nameHuffmanEncoded = stringReader.isHuffmanEncoded();
+ stringReader.reset();
+ }
+ firstValueRead = true;
+ return false;
+ } else {
+ if (!stringReader.read(input, value)) {
+ return false;
+ }
+ }
+ valueHuffmanEncoded = stringReader.isHuffmanEncoded();
+ stringReader.reset();
+ return true;
+ }
+
+ private void cleanUpAfterReading() {
+ name.setLength(0);
+ value.setLength(0);
+ firstValueRead = false;
+ state = State.READY;
+ }
+
+ private enum State {
+ READY,
+ INDEXED,
+ LITERAL_NEVER_INDEXED,
+ LITERAL,
+ LITERAL_WITH_INDEXING,
+ SIZE_UPDATE
+ }
+
+ HeaderTable getTable() {
+ return table;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/DecodingCallback.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2015, 2016, 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.net.httpclient.hpack;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Delivers results of the {@link Decoder#decode(ByteBuffer, boolean,
+ * DecodingCallback) decoding operation}.
+ *
+ * <p> Methods of the callback are never called by a decoder with any of the
+ * arguments being {@code null}.
+ *
+ * @apiNote
+ *
+ * <p> The callback provides methods for all possible <a
+ * href="https://tools.ietf.org/html/rfc7541#section-6">binary
+ * representations</a>. This could be useful for implementing an intermediary,
+ * logging, debugging, etc.
+ *
+ * <p> The callback is an interface in order to interoperate with lambdas (in
+ * the most common use case):
+ * <pre>{@code
+ * DecodingCallback callback = (name, value) -> System.out.println(name + ", " + value);
+ * }</pre>
+ *
+ * <p> Names and values are {@link CharSequence}s rather than {@link String}s in
+ * order to allow users to decide whether or not they need to create objects. A
+ * {@code CharSequence} might be used in-place, for example, to be appended to
+ * an {@link Appendable} (e.g. {@link StringBuilder}) and then discarded.
+ *
+ * <p> That said, if a passed {@code CharSequence} needs to outlast the method
+ * call, it needs to be copied.
+ *
+ * @since 9
+ */
+@FunctionalInterface
+public interface DecodingCallback {
+
+ /**
+ * A method the more specific methods of the callback forward their calls
+ * to.
+ *
+ * @param name
+ * header name
+ * @param value
+ * header value
+ */
+ void onDecoded(CharSequence name, CharSequence value);
+
+ /**
+ * A more finer-grained version of {@link #onDecoded(CharSequence,
+ * CharSequence)} that also reports on value sensitivity.
+ *
+ * <p> Value sensitivity must be considered, for example, when implementing
+ * an intermediary. A {@code value} is sensitive if it was represented as <a
+ * href="https://tools.ietf.org/html/rfc7541#section-6.2.3">Literal Header
+ * Field Never Indexed</a>.
+ *
+ * <p> It is required that intermediaries MUST use the {@linkplain
+ * Encoder#header(CharSequence, CharSequence, boolean) same representation}
+ * for encoding this header field in order to protect its value which is not
+ * to be put at risk by compressing it.
+ *
+ * @implSpec
+ *
+ * <p> The default implementation invokes {@code onDecoded(name, value)}.
+ *
+ * @param name
+ * header name
+ * @param value
+ * header value
+ * @param sensitive
+ * whether or not the value is sensitive
+ *
+ * @see #onLiteralNeverIndexed(int, CharSequence, CharSequence, boolean)
+ * @see #onLiteralNeverIndexed(CharSequence, boolean, CharSequence, boolean)
+ */
+ default void onDecoded(CharSequence name, CharSequence value,
+ boolean sensitive) {
+ onDecoded(name, value);
+ }
+
+ /**
+ * An <a href="https://tools.ietf.org/html/rfc7541#section-6.1">Indexed
+ * Header Field</a> decoded.
+ *
+ * @implSpec
+ *
+ * <p> The default implementation invokes
+ * {@code onDecoded(name, value, false)}.
+ *
+ * @param index
+ * index of an entry in the table
+ * @param name
+ * header name
+ * @param value
+ * header value
+ */
+ default void onIndexed(int index, CharSequence name, CharSequence value) {
+ onDecoded(name, value, false);
+ }
+
+ /**
+ * A <a href="https://tools.ietf.org/html/rfc7541#section-6.2.2">Literal
+ * Header Field without Indexing</a> decoded, where a {@code name} was
+ * referred by an {@code index}.
+ *
+ * @implSpec
+ *
+ * <p> The default implementation invokes
+ * {@code onDecoded(name, value, false)}.
+ *
+ * @param index
+ * index of an entry in the table
+ * @param name
+ * header name
+ * @param value
+ * header value
+ * @param valueHuffman
+ * if the {@code value} was Huffman encoded
+ */
+ default void onLiteral(int index, CharSequence name,
+ CharSequence value, boolean valueHuffman) {
+ onDecoded(name, value, false);
+ }
+
+ /**
+ * A <a href="https://tools.ietf.org/html/rfc7541#section-6.2.2">Literal
+ * Header Field without Indexing</a> decoded, where both a {@code name} and
+ * a {@code value} were literal.
+ *
+ * @implSpec
+ *
+ * <p> The default implementation invokes
+ * {@code onDecoded(name, value, false)}.
+ *
+ * @param name
+ * header name
+ * @param nameHuffman
+ * if the {@code name} was Huffman encoded
+ * @param value
+ * header value
+ * @param valueHuffman
+ * if the {@code value} was Huffman encoded
+ */
+ default void onLiteral(CharSequence name, boolean nameHuffman,
+ CharSequence value, boolean valueHuffman) {
+ onDecoded(name, value, false);
+ }
+
+ /**
+ * A <a href="https://tools.ietf.org/html/rfc7541#section-6.2.3">Literal
+ * Header Field Never Indexed</a> decoded, where a {@code name}
+ * was referred by an {@code index}.
+ *
+ * @implSpec
+ *
+ * <p> The default implementation invokes
+ * {@code onDecoded(name, value, true)}.
+ *
+ * @param index
+ * index of an entry in the table
+ * @param name
+ * header name
+ * @param value
+ * header value
+ * @param valueHuffman
+ * if the {@code value} was Huffman encoded
+ */
+ default void onLiteralNeverIndexed(int index, CharSequence name,
+ CharSequence value,
+ boolean valueHuffman) {
+ onDecoded(name, value, true);
+ }
+
+ /**
+ * A <a href="https://tools.ietf.org/html/rfc7541#section-6.2.3">Literal
+ * Header Field Never Indexed</a> decoded, where both a {@code
+ * name} and a {@code value} were literal.
+ *
+ * @implSpec
+ *
+ * <p> The default implementation invokes
+ * {@code onDecoded(name, value, true)}.
+ *
+ * @param name
+ * header name
+ * @param nameHuffman
+ * if the {@code name} was Huffman encoded
+ * @param value
+ * header value
+ * @param valueHuffman
+ * if the {@code value} was Huffman encoded
+ */
+ default void onLiteralNeverIndexed(CharSequence name, boolean nameHuffman,
+ CharSequence value, boolean valueHuffman) {
+ onDecoded(name, value, true);
+ }
+
+ /**
+ * A <a href="https://tools.ietf.org/html/rfc7541#section-6.2.1">Literal
+ * Header Field with Incremental Indexing</a> decoded, where a {@code name}
+ * was referred by an {@code index}.
+ *
+ * @implSpec
+ *
+ * <p> The default implementation invokes
+ * {@code onDecoded(name, value, false)}.
+ *
+ * @param index
+ * index of an entry in the table
+ * @param name
+ * header name
+ * @param value
+ * header value
+ * @param valueHuffman
+ * if the {@code value} was Huffman encoded
+ */
+ default void onLiteralWithIndexing(int index,
+ CharSequence name,
+ CharSequence value, boolean valueHuffman) {
+ onDecoded(name, value, false);
+ }
+
+ /**
+ * A <a href="https://tools.ietf.org/html/rfc7541#section-6.2.1">Literal
+ * Header Field with Incremental Indexing</a> decoded, where both a {@code
+ * name} and a {@code value} were literal.
+ *
+ * @implSpec
+ *
+ * <p> The default implementation invokes
+ * {@code onDecoded(name, value, false)}.
+ *
+ * @param name
+ * header name
+ * @param nameHuffman
+ * if the {@code name} was Huffman encoded
+ * @param value
+ * header value
+ * @param valueHuffman
+ * if the {@code value} was Huffman encoded
+ */
+ default void onLiteralWithIndexing(CharSequence name, boolean nameHuffman,
+ CharSequence value, boolean valueHuffman) {
+ onDecoded(name, value, false);
+ }
+
+ /**
+ * A <a href="https://tools.ietf.org/html/rfc7541#section-6.3">Dynamic Table
+ * Size Update</a> decoded.
+ *
+ * @implSpec
+ *
+ * <p> The default implementation does nothing.
+ *
+ * @param capacity
+ * new capacity of the header table
+ */
+ default void onSizeUpdate(int capacity) { }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/Encoder.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,429 @@
+/*
+ * Copyright (c) 2014, 2016, 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.net.httpclient.hpack;
+
+import java.nio.ByteBuffer;
+import java.nio.ReadOnlyBufferException;
+import java.util.LinkedList;
+import java.util.List;
+
+import static java.lang.String.format;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Encodes headers to their binary representation.
+ *
+ * <p>Typical lifecycle looks like this:
+ *
+ * <p> {@link #Encoder(int) new Encoder}
+ * ({@link #setMaxCapacity(int) setMaxCapacity}?
+ * {@link #encode(ByteBuffer) encode})*
+ *
+ * <p> Suppose headers are represented by {@code Map<String, List<String>>}. A
+ * supplier and a consumer of {@link ByteBuffer}s in forms of {@code
+ * Supplier<ByteBuffer>} and {@code Consumer<ByteBuffer>} respectively. Then to
+ * encode headers, the following approach might be used:
+ *
+ * <pre>{@code
+ * for (Map.Entry<String, List<String>> h : headers.entrySet()) {
+ * String name = h.getKey();
+ * for (String value : h.getValue()) {
+ * encoder.header(name, value); // Set up header
+ * boolean encoded;
+ * do {
+ * ByteBuffer b = buffersSupplier.get();
+ * encoded = encoder.encode(b); // Encode the header
+ * buffersConsumer.accept(b);
+ * } while (!encoded);
+ * }
+ * }
+ * }</pre>
+ *
+ * <p> Though the specification <a
+ * href="https://tools.ietf.org/html/rfc7541#section-2"> does not define</a> how
+ * an encoder is to be implemented, a default implementation is provided by the
+ * method {@link #header(CharSequence, CharSequence, boolean)}.
+ *
+ * <p> To provide a custom encoding implementation, {@code Encoder} has to be
+ * extended. A subclass then can access methods for encoding using specific
+ * representations (e.g. {@link #literal(int, CharSequence, boolean) literal},
+ * {@link #indexed(int) indexed}, etc.)
+ *
+ * @apiNote
+ *
+ * <p> An Encoder provides an incremental way of encoding headers.
+ * {@link #encode(ByteBuffer)} takes a buffer a returns a boolean indicating
+ * whether, or not, the buffer was sufficiently sized to hold the
+ * remaining of the encoded representation.
+ *
+ * <p> This way, there's no need to provide a buffer of a specific size, or to
+ * resize (and copy) the buffer on demand, when the remaining encoded
+ * representation will not fit in the buffer's remaining space. Instead, an
+ * array of existing buffers can be used, prepended with a frame that encloses
+ * the resulting header block afterwards.
+ *
+ * <p> Splitting the encoding operation into header set up and header encoding,
+ * separates long lived arguments ({@code name}, {@code value}, {@code
+ * sensitivity}, etc.) from the short lived ones (e.g. {@code buffer}),
+ * simplifying each operation itself.
+ *
+ * @implNote
+ *
+ * <p> The default implementation does not use dynamic table. It reports to a
+ * coupled Decoder a size update with the value of {@code 0}, and never changes
+ * it afterwards.
+ *
+ * @since 9
+ */
+public class Encoder {
+
+ // TODO: enum: no huffman/smart huffman/always huffman
+ private static final boolean DEFAULT_HUFFMAN = true;
+
+ private final IndexedWriter indexedWriter = new IndexedWriter();
+ private final LiteralWriter literalWriter = new LiteralWriter();
+ private final LiteralNeverIndexedWriter literalNeverIndexedWriter
+ = new LiteralNeverIndexedWriter();
+ private final LiteralWithIndexingWriter literalWithIndexingWriter
+ = new LiteralWithIndexingWriter();
+ private final SizeUpdateWriter sizeUpdateWriter = new SizeUpdateWriter();
+ private final BulkSizeUpdateWriter bulkSizeUpdateWriter
+ = new BulkSizeUpdateWriter();
+
+ private BinaryRepresentationWriter writer;
+ private final HeaderTable headerTable;
+
+ private boolean encoding;
+
+ private int maxCapacity;
+ private int currCapacity;
+ private int lastCapacity;
+ private long minCapacity;
+ private boolean capacityUpdate;
+ private boolean configuredCapacityUpdate;
+
+ /**
+ * Constructs an {@code Encoder} with the specified maximum capacity of the
+ * header table.
+ *
+ * <p> The value has to be agreed between decoder and encoder out-of-band,
+ * e.g. by a protocol that uses HPACK (see <a
+ * href="https://tools.ietf.org/html/rfc7541#section-4.2">4.2. Maximum Table
+ * Size</a>).
+ *
+ * @param maxCapacity
+ * a non-negative integer
+ *
+ * @throws IllegalArgumentException
+ * if maxCapacity is negative
+ */
+ public Encoder(int maxCapacity) {
+ if (maxCapacity < 0) {
+ throw new IllegalArgumentException("maxCapacity >= 0: " + maxCapacity);
+ }
+ // Initial maximum capacity update mechanics
+ minCapacity = Long.MAX_VALUE;
+ currCapacity = -1;
+ setMaxCapacity(maxCapacity);
+ headerTable = new HeaderTable(lastCapacity);
+ }
+
+ /**
+ * Sets up the given header {@code (name, value)}.
+ *
+ * <p> Fixates {@code name} and {@code value} for the duration of encoding.
+ *
+ * @param name
+ * the name
+ * @param value
+ * the value
+ *
+ * @throws NullPointerException
+ * if any of the arguments are {@code null}
+ * @throws IllegalStateException
+ * if the encoder hasn't fully encoded the previous header, or
+ * hasn't yet started to encode it
+ * @see #header(CharSequence, CharSequence, boolean)
+ */
+ public void header(CharSequence name, CharSequence value)
+ throws IllegalStateException {
+ header(name, value, false);
+ }
+
+ /**
+ * Sets up the given header {@code (name, value)} with possibly sensitive
+ * value.
+ *
+ * <p> Fixates {@code name} and {@code value} for the duration of encoding.
+ *
+ * @param name
+ * the name
+ * @param value
+ * the value
+ * @param sensitive
+ * whether or not the value is sensitive
+ *
+ * @throws NullPointerException
+ * if any of the arguments are {@code null}
+ * @throws IllegalStateException
+ * if the encoder hasn't fully encoded the previous header, or
+ * hasn't yet started to encode it
+ * @see #header(CharSequence, CharSequence)
+ * @see DecodingCallback#onDecoded(CharSequence, CharSequence, boolean)
+ */
+ public void header(CharSequence name, CharSequence value,
+ boolean sensitive) throws IllegalStateException {
+ // Arguably a good balance between complexity of implementation and
+ // efficiency of encoding
+ requireNonNull(name, "name");
+ requireNonNull(value, "value");
+ HeaderTable t = getHeaderTable();
+ int index = t.indexOf(name, value);
+ if (index > 0) {
+ indexed(index);
+ } else if (index < 0) {
+ if (sensitive) {
+ literalNeverIndexed(-index, value, DEFAULT_HUFFMAN);
+ } else {
+ literal(-index, value, DEFAULT_HUFFMAN);
+ }
+ } else {
+ if (sensitive) {
+ literalNeverIndexed(name, DEFAULT_HUFFMAN, value, DEFAULT_HUFFMAN);
+ } else {
+ literal(name, DEFAULT_HUFFMAN, value, DEFAULT_HUFFMAN);
+ }
+ }
+ }
+
+ /**
+ * Sets a maximum capacity of the header table.
+ *
+ * <p> The value has to be agreed between decoder and encoder out-of-band,
+ * e.g. by a protocol that uses HPACK (see <a
+ * href="https://tools.ietf.org/html/rfc7541#section-4.2">4.2. Maximum Table
+ * Size</a>).
+ *
+ * <p> May be called any number of times after or before a complete header
+ * has been encoded.
+ *
+ * <p> If the encoder decides to change the actual capacity, an update will
+ * be encoded before a new encoding operation starts.
+ *
+ * @param capacity
+ * a non-negative integer
+ *
+ * @throws IllegalArgumentException
+ * if capacity is negative
+ * @throws IllegalStateException
+ * if the encoder hasn't fully encoded the previous header, or
+ * hasn't yet started to encode it
+ */
+ public void setMaxCapacity(int capacity) {
+ checkEncoding();
+ if (capacity < 0) {
+ throw new IllegalArgumentException("capacity >= 0: " + capacity);
+ }
+ int calculated = calculateCapacity(capacity);
+ if (calculated < 0 || calculated > capacity) {
+ throw new IllegalArgumentException(
+ format("0 <= calculated <= capacity: calculated=%s, capacity=%s",
+ calculated, capacity));
+ }
+ capacityUpdate = true;
+ // maxCapacity needs to be updated unconditionally, so the encoder
+ // always has the newest one (in case it decides to update it later
+ // unsolicitedly)
+ // Suppose maxCapacity = 4096, and the encoder has decided to use only
+ // 2048. It later can choose anything else from the region [0, 4096].
+ maxCapacity = capacity;
+ lastCapacity = calculated;
+ minCapacity = Math.min(minCapacity, lastCapacity);
+ }
+
+ protected int calculateCapacity(int maxCapacity) {
+ // Default implementation of the Encoder won't add anything to the
+ // table, therefore no need for a table space
+ return 0;
+ }
+
+ /**
+ * Encodes the {@linkplain #header(CharSequence, CharSequence) set up}
+ * header into the given buffer.
+ *
+ * <p> The encoder writes as much as possible of the header's binary
+ * representation into the given buffer, starting at the buffer's position,
+ * and increments its position to reflect the bytes written. The buffer's
+ * mark and limit will not be modified.
+ *
+ * <p> Once the method has returned {@code true}, the current header is
+ * deemed encoded. A new header may be set up.
+ *
+ * @param headerBlock
+ * the buffer to encode the header into, may be empty
+ *
+ * @return {@code true} if the current header has been fully encoded,
+ * {@code false} otherwise
+ *
+ * @throws NullPointerException
+ * if the buffer is {@code null}
+ * @throws ReadOnlyBufferException
+ * if this buffer is read-only
+ * @throws IllegalStateException
+ * if there is no set up header
+ */
+ public final boolean encode(ByteBuffer headerBlock) {
+ if (!encoding) {
+ throw new IllegalStateException("A header hasn't been set up");
+ }
+ if (!prependWithCapacityUpdate(headerBlock)) {
+ return false;
+ }
+ boolean done = writer.write(headerTable, headerBlock);
+ if (done) {
+ writer.reset(); // FIXME: WHY?
+ encoding = false;
+ }
+ return done;
+ }
+
+ private boolean prependWithCapacityUpdate(ByteBuffer headerBlock) {
+ if (capacityUpdate) {
+ if (!configuredCapacityUpdate) {
+ List<Integer> sizes = new LinkedList<>();
+ if (minCapacity < currCapacity) {
+ sizes.add((int) minCapacity);
+ if (minCapacity != lastCapacity) {
+ sizes.add(lastCapacity);
+ }
+ } else if (lastCapacity != currCapacity) {
+ sizes.add(lastCapacity);
+ }
+ bulkSizeUpdateWriter.maxHeaderTableSizes(sizes);
+ configuredCapacityUpdate = true;
+ }
+ boolean done = bulkSizeUpdateWriter.write(headerTable, headerBlock);
+ if (done) {
+ minCapacity = lastCapacity;
+ currCapacity = lastCapacity;
+ bulkSizeUpdateWriter.reset();
+ capacityUpdate = false;
+ configuredCapacityUpdate = false;
+ }
+ return done;
+ }
+ return true;
+ }
+
+ protected final void indexed(int index) throws IndexOutOfBoundsException {
+ checkEncoding();
+ encoding = true;
+ writer = indexedWriter.index(index);
+ }
+
+ protected final void literal(int index, CharSequence value,
+ boolean useHuffman)
+ throws IndexOutOfBoundsException {
+ checkEncoding();
+ encoding = true;
+ writer = literalWriter
+ .index(index).value(value, useHuffman);
+ }
+
+ protected final void literal(CharSequence name, boolean nameHuffman,
+ CharSequence value, boolean valueHuffman) {
+ checkEncoding();
+ encoding = true;
+ writer = literalWriter
+ .name(name, nameHuffman).value(value, valueHuffman);
+ }
+
+ protected final void literalNeverIndexed(int index,
+ CharSequence value,
+ boolean valueHuffman)
+ throws IndexOutOfBoundsException {
+ checkEncoding();
+ encoding = true;
+ writer = literalNeverIndexedWriter
+ .index(index).value(value, valueHuffman);
+ }
+
+ protected final void literalNeverIndexed(CharSequence name,
+ boolean nameHuffman,
+ CharSequence value,
+ boolean valueHuffman) {
+ checkEncoding();
+ encoding = true;
+ writer = literalNeverIndexedWriter
+ .name(name, nameHuffman).value(value, valueHuffman);
+ }
+
+ protected final void literalWithIndexing(int index,
+ CharSequence value,
+ boolean valueHuffman)
+ throws IndexOutOfBoundsException {
+ checkEncoding();
+ encoding = true;
+ writer = literalWithIndexingWriter
+ .index(index).value(value, valueHuffman);
+ }
+
+ protected final void literalWithIndexing(CharSequence name,
+ boolean nameHuffman,
+ CharSequence value,
+ boolean valueHuffman) {
+ checkEncoding();
+ encoding = true;
+ writer = literalWithIndexingWriter
+ .name(name, nameHuffman).value(value, valueHuffman);
+ }
+
+ protected final void sizeUpdate(int capacity)
+ throws IllegalArgumentException {
+ checkEncoding();
+ // Ensure subclass follows the contract
+ if (capacity > this.maxCapacity) {
+ throw new IllegalArgumentException(
+ format("capacity <= maxCapacity: capacity=%s, maxCapacity=%s",
+ capacity, maxCapacity));
+ }
+ writer = sizeUpdateWriter.maxHeaderTableSize(capacity);
+ }
+
+ protected final int getMaxCapacity() {
+ return maxCapacity;
+ }
+
+ protected final HeaderTable getHeaderTable() {
+ return headerTable;
+ }
+
+ protected final void checkEncoding() {
+ if (encoding) {
+ throw new IllegalStateException(
+ "Previous encoding operation hasn't finished yet");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/HeaderTable.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,511 @@
+/*
+ * Copyright (c) 2014, 2016, 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.net.httpclient.hpack;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import static java.lang.String.format;
+
+//
+// Header Table combined from two tables: static and dynamic.
+//
+// There is a single address space for index values. Index-aware methods
+// correspond to the table as a whole. Size-aware methods only to the dynamic
+// part of it.
+//
+final class HeaderTable {
+
+ private static final HeaderField[] staticTable = {
+ null, // To make index 1-based, instead of 0-based
+ new HeaderField(":authority"),
+ new HeaderField(":method", "GET"),
+ new HeaderField(":method", "POST"),
+ new HeaderField(":path", "/"),
+ new HeaderField(":path", "/index.html"),
+ new HeaderField(":scheme", "http"),
+ new HeaderField(":scheme", "https"),
+ new HeaderField(":status", "200"),
+ new HeaderField(":status", "204"),
+ new HeaderField(":status", "206"),
+ new HeaderField(":status", "304"),
+ new HeaderField(":status", "400"),
+ new HeaderField(":status", "404"),
+ new HeaderField(":status", "500"),
+ new HeaderField("accept-charset"),
+ new HeaderField("accept-encoding", "gzip, deflate"),
+ new HeaderField("accept-language"),
+ new HeaderField("accept-ranges"),
+ new HeaderField("accept"),
+ new HeaderField("access-control-allow-origin"),
+ new HeaderField("age"),
+ new HeaderField("allow"),
+ new HeaderField("authorization"),
+ new HeaderField("cache-control"),
+ new HeaderField("content-disposition"),
+ new HeaderField("content-encoding"),
+ new HeaderField("content-language"),
+ new HeaderField("content-length"),
+ new HeaderField("content-location"),
+ new HeaderField("content-range"),
+ new HeaderField("content-type"),
+ new HeaderField("cookie"),
+ new HeaderField("date"),
+ new HeaderField("etag"),
+ new HeaderField("expect"),
+ new HeaderField("expires"),
+ new HeaderField("from"),
+ new HeaderField("host"),
+ new HeaderField("if-match"),
+ new HeaderField("if-modified-since"),
+ new HeaderField("if-none-match"),
+ new HeaderField("if-range"),
+ new HeaderField("if-unmodified-since"),
+ new HeaderField("last-modified"),
+ new HeaderField("link"),
+ new HeaderField("location"),
+ new HeaderField("max-forwards"),
+ new HeaderField("proxy-authenticate"),
+ new HeaderField("proxy-authorization"),
+ new HeaderField("range"),
+ new HeaderField("referer"),
+ new HeaderField("refresh"),
+ new HeaderField("retry-after"),
+ new HeaderField("server"),
+ new HeaderField("set-cookie"),
+ new HeaderField("strict-transport-security"),
+ new HeaderField("transfer-encoding"),
+ new HeaderField("user-agent"),
+ new HeaderField("vary"),
+ new HeaderField("via"),
+ new HeaderField("www-authenticate")
+ };
+
+ private static final int STATIC_TABLE_LENGTH = staticTable.length - 1;
+ private static final int ENTRY_SIZE = 32;
+ private static final Map<String, LinkedHashMap<String, Integer>> staticIndexes;
+
+ static {
+ staticIndexes = new HashMap<>(STATIC_TABLE_LENGTH);
+ for (int i = 1; i <= STATIC_TABLE_LENGTH; i++) {
+ HeaderField f = staticTable[i];
+ Map<String, Integer> values = staticIndexes
+ .computeIfAbsent(f.name, k -> new LinkedHashMap<>());
+ values.put(f.value, i);
+ }
+ }
+
+ private final Table dynamicTable = new Table(0);
+ private int maxSize;
+ private int size;
+
+ public HeaderTable(int maxSize) {
+ setMaxSize(maxSize);
+ }
+
+ //
+ // The method returns:
+ //
+ // * a positive integer i where i (i = [1..Integer.MAX_VALUE]) is an
+ // index of an entry with a header (n, v), where n.equals(name) &&
+ // v.equals(value)
+ //
+ // * a negative integer j where j (j = [-Integer.MAX_VALUE..-1]) is an
+ // index of an entry with a header (n, v), where n.equals(name)
+ //
+ // * 0 if there's no entry e such that e.getName().equals(name)
+ //
+ // The rationale behind this design is to allow to pack more useful data
+ // into a single invocation, facilitating a single pass where possible
+ // (the idea is the same as in java.util.Arrays.binarySearch(int[], int)).
+ //
+ public int indexOf(CharSequence name, CharSequence value) {
+ // Invoking toString() will possibly allocate Strings for the sake of
+ // the search, which doesn't feel right.
+ String n = name.toString();
+ String v = value.toString();
+
+ // 1. Try exact match in the static region
+ Map<String, Integer> values = staticIndexes.get(n);
+ if (values != null) {
+ Integer idx = values.get(v);
+ if (idx != null) {
+ return idx;
+ }
+ }
+ // 2. Try exact match in the dynamic region
+ int didx = dynamicTable.indexOf(n, v);
+ if (didx > 0) {
+ return STATIC_TABLE_LENGTH + didx;
+ } else if (didx < 0) {
+ if (values != null) {
+ // 3. Return name match from the static region
+ return -values.values().iterator().next(); // Iterator allocation
+ } else {
+ // 4. Return name match from the dynamic region
+ return -STATIC_TABLE_LENGTH + didx;
+ }
+ } else {
+ if (values != null) {
+ // 3. Return name match from the static region
+ return -values.values().iterator().next(); // Iterator allocation
+ } else {
+ return 0;
+ }
+ }
+ }
+
+ public int size() {
+ return size;
+ }
+
+ public int maxSize() {
+ return maxSize;
+ }
+
+ public int length() {
+ return STATIC_TABLE_LENGTH + dynamicTable.size();
+ }
+
+ HeaderField get(int index) {
+ checkIndex(index);
+ if (index <= STATIC_TABLE_LENGTH) {
+ return staticTable[index];
+ } else {
+ return dynamicTable.get(index - STATIC_TABLE_LENGTH);
+ }
+ }
+
+ void put(CharSequence name, CharSequence value) {
+ // Invoking toString() will possibly allocate Strings. But that's
+ // unavoidable at this stage. If a CharSequence is going to be stored in
+ // the table, it must not be mutable (e.g. for the sake of hashing).
+ put(new HeaderField(name.toString(), value.toString()));
+ }
+
+ private void put(HeaderField h) {
+ int entrySize = sizeOf(h);
+ while (entrySize > maxSize - size && size != 0) {
+ evictEntry();
+ }
+ if (entrySize > maxSize - size) {
+ return;
+ }
+ size += entrySize;
+ dynamicTable.add(h);
+ }
+
+ void setMaxSize(int maxSize) {
+ if (maxSize < 0) {
+ throw new IllegalArgumentException
+ ("maxSize >= 0: maxSize=" + maxSize);
+ }
+ while (maxSize < size && size != 0) {
+ evictEntry();
+ }
+ this.maxSize = maxSize;
+ int upperBound = (maxSize / ENTRY_SIZE) + 1;
+ this.dynamicTable.setCapacity(upperBound);
+ }
+
+ HeaderField evictEntry() {
+ HeaderField f = dynamicTable.remove();
+ size -= sizeOf(f);
+ return f;
+ }
+
+ @Override
+ public String toString() {
+ double used = maxSize == 0 ? 0 : 100 * (((double) size) / maxSize);
+ return format("entries: %d; used %s/%s (%.1f%%)", dynamicTable.size(),
+ size, maxSize, used);
+ }
+
+ int checkIndex(int index) {
+ if (index < 1 || index > STATIC_TABLE_LENGTH + dynamicTable.size()) {
+ throw new IllegalArgumentException(
+ format("1 <= index <= length(): index=%s, length()=%s",
+ index, length()));
+ }
+ return index;
+ }
+
+ int sizeOf(HeaderField f) {
+ return f.name.length() + f.value.length() + ENTRY_SIZE;
+ }
+
+ //
+ // Diagnostic information in the form used in the RFC 7541
+ //
+ String getStateString() {
+ if (size == 0) {
+ return "empty.";
+ }
+
+ StringBuilder b = new StringBuilder();
+ for (int i = 1, size = dynamicTable.size(); i <= size; i++) {
+ HeaderField e = dynamicTable.get(i);
+ b.append(format("[%3d] (s = %3d) %s: %s\n", i,
+ sizeOf(e), e.name, e.value));
+ }
+ b.append(format(" Table size:%4s", this.size));
+ return b.toString();
+ }
+
+ // Convert to a Value Object (JDK-8046159)?
+ static final class HeaderField {
+
+ final String name;
+ final String value;
+
+ public HeaderField(String name) {
+ this(name, "");
+ }
+
+ public HeaderField(String name, String value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return value.isEmpty() ? name : name + ": " + value;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ HeaderField that = (HeaderField) o;
+ return name.equals(that.name) && value.equals(that.value);
+ }
+
+ @Override
+ public int hashCode() {
+ return 31 * (name.hashCode()) + value.hashCode();
+ }
+ }
+
+ //
+ // In order to be able to find an index of an entry with the given contents
+ // in the dynamic table an effective inverse mapping is needed. Here's a
+ // simple idea behind such a mapping.
+ //
+ // # The problem:
+ //
+ // We have a queue with an O(1) lookup by index:
+ //
+ // get: index -> x
+ //
+ // What we also want is an O(1) reverse lookup:
+ //
+ // indexOf: x -> index
+ //
+ // # Solution:
+ //
+ // Let's store an inverse mapping as a Map<X, Integer>. This have a problem
+ // that when a new element is added to the queue all indexes in the map
+ // becomes invalid. Namely, each i becomes shifted by 1 to the right:
+ //
+ // i -> i + 1
+ //
+ // And the new element is assigned with an index of 1. This would seem to
+ // require a pass through the map incrementing all indexes (map values) by
+ // 1, which is O(n).
+ //
+ // The good news is we can do much better then this!
+ //
+ // Let's create a single field of type long, called 'counter'. Then each
+ // time a new element 'x' is added to the queue, a value of this field gets
+ // incremented. Then the resulting value of the 'counter_x' is then put as a
+ // value under key 'x' to the map:
+ //
+ // map.put(x, counter_x)
+ //
+ // It gives us a map that maps an element to a value the counter had at the
+ // time the element had been added.
+ //
+ // In order to retrieve an index of any element 'x' in the queue (at any
+ // given time) we simply need to subtract the value (the snapshot of the
+ // counter at the time when the 'x' was added) from the current value of the
+ // counter. This operation basically answers the question:
+ //
+ // How many elements ago 'x' was the tail of the queue?
+ //
+ // Which is the same as its index in the queue now. Given, of course, it's
+ // still in the queue.
+ //
+ // I'm pretty sure in a real life long overflow will never happen, so it's
+ // not too practical to add recalibrating code, but a pedantic person might
+ // want to do so:
+ //
+ // if (counter == Long.MAX_VALUE) {
+ // recalibrate();
+ // }
+ //
+ // Where 'recalibrate()' goes through the table doing this:
+ //
+ // value -= counter
+ //
+ // That's given, of course, the size of the table itself is less than
+ // Long.MAX_VALUE :-)
+ //
+ private static final class Table {
+
+ private final Map<String, Map<String, Long>> map;
+ private final CircularBuffer<HeaderField> buffer;
+ private long counter = 1;
+
+ Table(int capacity) {
+ buffer = new CircularBuffer<>(capacity);
+ map = new HashMap<>(capacity);
+ }
+
+ void add(HeaderField f) {
+ buffer.add(f);
+ Map<String, Long> values = map.computeIfAbsent(f.name, k -> new HashMap<>());
+ values.put(f.value, counter++);
+ }
+
+ HeaderField get(int index) {
+ return buffer.get(index - 1);
+ }
+
+ int indexOf(String name, String value) {
+ Map<String, Long> values = map.get(name);
+ if (values == null) {
+ return 0;
+ }
+ Long index = values.get(value);
+ if (index != null) {
+ return (int) (counter - index);
+ } else {
+ assert !values.isEmpty();
+ Long any = values.values().iterator().next(); // Iterator allocation
+ return -(int) (counter - any);
+ }
+ }
+
+ HeaderField remove() {
+ HeaderField f = buffer.remove();
+ Map<String, Long> values = map.get(f.name);
+ Long index = values.remove(f.value);
+ assert index != null;
+ if (values.isEmpty()) {
+ map.remove(f.name);
+ }
+ return f;
+ }
+
+ int size() {
+ return buffer.size;
+ }
+
+ public void setCapacity(int capacity) {
+ buffer.resize(capacity);
+ }
+ }
+
+ // head
+ // v
+ // [ ][ ][A][B][C][D][ ][ ][ ]
+ // ^
+ // tail
+ //
+ // |<- size ->| (4)
+ // |<------ capacity ------->| (9)
+ //
+ static final class CircularBuffer<E> {
+
+ int tail, head, size, capacity;
+ Object[] elements;
+
+ CircularBuffer(int capacity) {
+ this.capacity = capacity;
+ elements = new Object[capacity];
+ }
+
+ void add(E elem) {
+ if (size == capacity) {
+ throw new IllegalStateException(
+ format("No room for '%s': capacity=%s", elem, capacity));
+ }
+ elements[head] = elem;
+ head = (head + 1) % capacity;
+ size++;
+ }
+
+ @SuppressWarnings("unchecked")
+ E remove() {
+ if (size == 0) {
+ throw new NoSuchElementException("Empty");
+ }
+ E elem = (E) elements[tail];
+ elements[tail] = null;
+ tail = (tail + 1) % capacity;
+ size--;
+ return elem;
+ }
+
+ @SuppressWarnings("unchecked")
+ E get(int index) {
+ if (index < 0 || index >= size) {
+ throw new IndexOutOfBoundsException(
+ format("0 <= index <= capacity: index=%s, capacity=%s",
+ index, capacity));
+ }
+ int idx = (tail + (size - index - 1)) % capacity;
+ return (E) elements[idx];
+ }
+
+ public void resize(int newCapacity) {
+ if (newCapacity < size) {
+ throw new IllegalStateException(
+ format("newCapacity >= size: newCapacity=%s, size=%s",
+ newCapacity, size));
+ }
+
+ Object[] newElements = new Object[newCapacity];
+
+ if (tail < head || size == 0) {
+ System.arraycopy(elements, tail, newElements, 0, size);
+ } else {
+ System.arraycopy(elements, tail, newElements, 0, elements.length - tail);
+ System.arraycopy(elements, 0, newElements, elements.length - tail, head);
+ }
+
+ elements = newElements;
+ tail = 0;
+ head = size;
+ this.capacity = newCapacity;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/Huffman.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,676 @@
+/*
+ * Copyright (c) 2014, 2016, 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.net.httpclient.hpack;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.ByteBuffer;
+
+import static java.lang.String.format;
+
+/**
+ * Huffman coding table.
+ *
+ * <p> Instances of this class are safe for use by multiple threads.
+ *
+ * @since 9
+ */
+public final class Huffman {
+
+ // TODO: check if reset is done in both reader and writer
+
+ static final class Reader {
+
+ private Node curr; // position in the trie
+ private int len; // length of the path from the root to 'curr'
+ private int p; // byte probe
+
+ {
+ reset();
+ }
+
+ public void read(ByteBuffer source, Appendable destination,
+ boolean isLast) {
+ read(source, destination, true, isLast);
+ }
+
+ // Takes 'isLast' rather than returns whether the reading is done or
+ // not, for more informative exceptions.
+ void read(ByteBuffer source, Appendable destination, boolean reportEOS,
+ boolean isLast) {
+
+ Node c = curr;
+ int l = len;
+ /*
+ Since ByteBuffer is itself stateful, its position is
+ remembered here NOT as a part of Reader's state,
+ but to set it back in the case of a failure
+ */
+ int pos = source.position();
+
+ while (source.hasRemaining()) {
+ int d = source.get();
+ for (; p != 0; p >>= 1) {
+ c = c.getChild(p & d);
+ l++;
+ if (c.isLeaf()) {
+ if (reportEOS && c.isEOSPath) {
+ throw new IllegalArgumentException("Encountered EOS");
+ }
+ try {
+ destination.append(c.getChar());
+ } catch (RuntimeException | Error e) {
+ source.position(pos);
+ throw e;
+ } catch (IOException e) {
+ source.position(pos);
+ throw new UncheckedIOException(e);
+ }
+ c = INSTANCE.root;
+ l = 0;
+ }
+ curr = c;
+ len = l;
+ }
+ resetProbe();
+ pos++;
+ }
+ if (!isLast) {
+ return; // it's too early to jump to any conclusions, let's wait
+ }
+ if (c.isLeaf()) {
+ return; // it's perfectly ok, no extra padding bits
+ }
+ if (c.isEOSPath && len <= 7) {
+ return; // it's ok, some extra padding bits
+ }
+ if (c.isEOSPath) {
+ throw new IllegalArgumentException(
+ "Padding is too long (len=" + len + ") " +
+ "or unexpected end of data");
+ }
+ throw new IllegalArgumentException(
+ "Not a EOS prefix padding or unexpected end of data");
+ }
+
+ public void reset() {
+ curr = INSTANCE.root;
+ len = 0;
+ resetProbe();
+ }
+
+ private void resetProbe() {
+ p = 0x80;
+ }
+ }
+
+ static final class Writer {
+
+ private int pos; // position in 'source'
+ private int avail = 8; // number of least significant bits available in 'curr'
+ private int curr; // next byte to put to the destination
+ private int rem; // number of least significant bits in 'code' yet to be processed
+ private int code; // current code being written
+
+ private CharSequence source;
+ private int end;
+
+ public Writer from(CharSequence input, int start, int end) {
+ if (start < 0 || end < 0 || end > input.length() || start > end) {
+ throw new IndexOutOfBoundsException(
+ String.format("input.length()=%s, start=%s, end=%s",
+ input.length(), start, end));
+ }
+ pos = start;
+ this.end = end;
+ this.source = input;
+ return this;
+ }
+
+ public boolean write(ByteBuffer destination) {
+ for (; pos < end; pos++) {
+ if (rem == 0) {
+ Code desc = INSTANCE.codeOf(source.charAt(pos));
+ rem = desc.length;
+ code = desc.code;
+ }
+ while (rem > 0) {
+ if (rem < avail) {
+ curr |= (code << (avail - rem));
+ avail -= rem;
+ rem = 0;
+ } else {
+ int c = (curr | (code >>> (rem - avail)));
+ if (destination.hasRemaining()) {
+ destination.put((byte) c);
+ } else {
+ return false;
+ }
+ curr = c;
+ code <<= (32 - rem + avail); // throw written bits off the cliff (is this Sparta?)
+ code >>>= (32 - rem + avail); // return to the position
+ rem -= avail;
+ curr = 0;
+ avail = 8;
+ }
+ }
+ }
+
+ if (avail < 8) { // have to pad
+ if (destination.hasRemaining()) {
+ destination.put((byte) (curr | (INSTANCE.EOS.code >>> (INSTANCE.EOS.length - avail))));
+ avail = 8;
+ } else {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public Writer reset() {
+ source = null;
+ end = -1;
+ pos = -1;
+ avail = 8;
+ curr = 0;
+ code = 0;
+ return this;
+ }
+ }
+
+ /**
+ * Shared instance.
+ */
+ public static final Huffman INSTANCE = new Huffman();
+
+ private final Code EOS = new Code(0x3fffffff, 30);
+ private final Code[] codes = new Code[257];
+ private final Node root = new Node() {
+ @Override
+ public String toString() { return "root"; }
+ };
+
+ // TODO: consider builder and immutable trie
+ private Huffman() {
+ // @formatter:off
+ addChar(0, 0x1ff8, 13);
+ addChar(1, 0x7fffd8, 23);
+ addChar(2, 0xfffffe2, 28);
+ addChar(3, 0xfffffe3, 28);
+ addChar(4, 0xfffffe4, 28);
+ addChar(5, 0xfffffe5, 28);
+ addChar(6, 0xfffffe6, 28);
+ addChar(7, 0xfffffe7, 28);
+ addChar(8, 0xfffffe8, 28);
+ addChar(9, 0xffffea, 24);
+ addChar(10, 0x3ffffffc, 30);
+ addChar(11, 0xfffffe9, 28);
+ addChar(12, 0xfffffea, 28);
+ addChar(13, 0x3ffffffd, 30);
+ addChar(14, 0xfffffeb, 28);
+ addChar(15, 0xfffffec, 28);
+ addChar(16, 0xfffffed, 28);
+ addChar(17, 0xfffffee, 28);
+ addChar(18, 0xfffffef, 28);
+ addChar(19, 0xffffff0, 28);
+ addChar(20, 0xffffff1, 28);
+ addChar(21, 0xffffff2, 28);
+ addChar(22, 0x3ffffffe, 30);
+ addChar(23, 0xffffff3, 28);
+ addChar(24, 0xffffff4, 28);
+ addChar(25, 0xffffff5, 28);
+ addChar(26, 0xffffff6, 28);
+ addChar(27, 0xffffff7, 28);
+ addChar(28, 0xffffff8, 28);
+ addChar(29, 0xffffff9, 28);
+ addChar(30, 0xffffffa, 28);
+ addChar(31, 0xffffffb, 28);
+ addChar(32, 0x14, 6);
+ addChar(33, 0x3f8, 10);
+ addChar(34, 0x3f9, 10);
+ addChar(35, 0xffa, 12);
+ addChar(36, 0x1ff9, 13);
+ addChar(37, 0x15, 6);
+ addChar(38, 0xf8, 8);
+ addChar(39, 0x7fa, 11);
+ addChar(40, 0x3fa, 10);
+ addChar(41, 0x3fb, 10);
+ addChar(42, 0xf9, 8);
+ addChar(43, 0x7fb, 11);
+ addChar(44, 0xfa, 8);
+ addChar(45, 0x16, 6);
+ addChar(46, 0x17, 6);
+ addChar(47, 0x18, 6);
+ addChar(48, 0x0, 5);
+ addChar(49, 0x1, 5);
+ addChar(50, 0x2, 5);
+ addChar(51, 0x19, 6);
+ addChar(52, 0x1a, 6);
+ addChar(53, 0x1b, 6);
+ addChar(54, 0x1c, 6);
+ addChar(55, 0x1d, 6);
+ addChar(56, 0x1e, 6);
+ addChar(57, 0x1f, 6);
+ addChar(58, 0x5c, 7);
+ addChar(59, 0xfb, 8);
+ addChar(60, 0x7ffc, 15);
+ addChar(61, 0x20, 6);
+ addChar(62, 0xffb, 12);
+ addChar(63, 0x3fc, 10);
+ addChar(64, 0x1ffa, 13);
+ addChar(65, 0x21, 6);
+ addChar(66, 0x5d, 7);
+ addChar(67, 0x5e, 7);
+ addChar(68, 0x5f, 7);
+ addChar(69, 0x60, 7);
+ addChar(70, 0x61, 7);
+ addChar(71, 0x62, 7);
+ addChar(72, 0x63, 7);
+ addChar(73, 0x64, 7);
+ addChar(74, 0x65, 7);
+ addChar(75, 0x66, 7);
+ addChar(76, 0x67, 7);
+ addChar(77, 0x68, 7);
+ addChar(78, 0x69, 7);
+ addChar(79, 0x6a, 7);
+ addChar(80, 0x6b, 7);
+ addChar(81, 0x6c, 7);
+ addChar(82, 0x6d, 7);
+ addChar(83, 0x6e, 7);
+ addChar(84, 0x6f, 7);
+ addChar(85, 0x70, 7);
+ addChar(86, 0x71, 7);
+ addChar(87, 0x72, 7);
+ addChar(88, 0xfc, 8);
+ addChar(89, 0x73, 7);
+ addChar(90, 0xfd, 8);
+ addChar(91, 0x1ffb, 13);
+ addChar(92, 0x7fff0, 19);
+ addChar(93, 0x1ffc, 13);
+ addChar(94, 0x3ffc, 14);
+ addChar(95, 0x22, 6);
+ addChar(96, 0x7ffd, 15);
+ addChar(97, 0x3, 5);
+ addChar(98, 0x23, 6);
+ addChar(99, 0x4, 5);
+ addChar(100, 0x24, 6);
+ addChar(101, 0x5, 5);
+ addChar(102, 0x25, 6);
+ addChar(103, 0x26, 6);
+ addChar(104, 0x27, 6);
+ addChar(105, 0x6, 5);
+ addChar(106, 0x74, 7);
+ addChar(107, 0x75, 7);
+ addChar(108, 0x28, 6);
+ addChar(109, 0x29, 6);
+ addChar(110, 0x2a, 6);
+ addChar(111, 0x7, 5);
+ addChar(112, 0x2b, 6);
+ addChar(113, 0x76, 7);
+ addChar(114, 0x2c, 6);
+ addChar(115, 0x8, 5);
+ addChar(116, 0x9, 5);
+ addChar(117, 0x2d, 6);
+ addChar(118, 0x77, 7);
+ addChar(119, 0x78, 7);
+ addChar(120, 0x79, 7);
+ addChar(121, 0x7a, 7);
+ addChar(122, 0x7b, 7);
+ addChar(123, 0x7ffe, 15);
+ addChar(124, 0x7fc, 11);
+ addChar(125, 0x3ffd, 14);
+ addChar(126, 0x1ffd, 13);
+ addChar(127, 0xffffffc, 28);
+ addChar(128, 0xfffe6, 20);
+ addChar(129, 0x3fffd2, 22);
+ addChar(130, 0xfffe7, 20);
+ addChar(131, 0xfffe8, 20);
+ addChar(132, 0x3fffd3, 22);
+ addChar(133, 0x3fffd4, 22);
+ addChar(134, 0x3fffd5, 22);
+ addChar(135, 0x7fffd9, 23);
+ addChar(136, 0x3fffd6, 22);
+ addChar(137, 0x7fffda, 23);
+ addChar(138, 0x7fffdb, 23);
+ addChar(139, 0x7fffdc, 23);
+ addChar(140, 0x7fffdd, 23);
+ addChar(141, 0x7fffde, 23);
+ addChar(142, 0xffffeb, 24);
+ addChar(143, 0x7fffdf, 23);
+ addChar(144, 0xffffec, 24);
+ addChar(145, 0xffffed, 24);
+ addChar(146, 0x3fffd7, 22);
+ addChar(147, 0x7fffe0, 23);
+ addChar(148, 0xffffee, 24);
+ addChar(149, 0x7fffe1, 23);
+ addChar(150, 0x7fffe2, 23);
+ addChar(151, 0x7fffe3, 23);
+ addChar(152, 0x7fffe4, 23);
+ addChar(153, 0x1fffdc, 21);
+ addChar(154, 0x3fffd8, 22);
+ addChar(155, 0x7fffe5, 23);
+ addChar(156, 0x3fffd9, 22);
+ addChar(157, 0x7fffe6, 23);
+ addChar(158, 0x7fffe7, 23);
+ addChar(159, 0xffffef, 24);
+ addChar(160, 0x3fffda, 22);
+ addChar(161, 0x1fffdd, 21);
+ addChar(162, 0xfffe9, 20);
+ addChar(163, 0x3fffdb, 22);
+ addChar(164, 0x3fffdc, 22);
+ addChar(165, 0x7fffe8, 23);
+ addChar(166, 0x7fffe9, 23);
+ addChar(167, 0x1fffde, 21);
+ addChar(168, 0x7fffea, 23);
+ addChar(169, 0x3fffdd, 22);
+ addChar(170, 0x3fffde, 22);
+ addChar(171, 0xfffff0, 24);
+ addChar(172, 0x1fffdf, 21);
+ addChar(173, 0x3fffdf, 22);
+ addChar(174, 0x7fffeb, 23);
+ addChar(175, 0x7fffec, 23);
+ addChar(176, 0x1fffe0, 21);
+ addChar(177, 0x1fffe1, 21);
+ addChar(178, 0x3fffe0, 22);
+ addChar(179, 0x1fffe2, 21);
+ addChar(180, 0x7fffed, 23);
+ addChar(181, 0x3fffe1, 22);
+ addChar(182, 0x7fffee, 23);
+ addChar(183, 0x7fffef, 23);
+ addChar(184, 0xfffea, 20);
+ addChar(185, 0x3fffe2, 22);
+ addChar(186, 0x3fffe3, 22);
+ addChar(187, 0x3fffe4, 22);
+ addChar(188, 0x7ffff0, 23);
+ addChar(189, 0x3fffe5, 22);
+ addChar(190, 0x3fffe6, 22);
+ addChar(191, 0x7ffff1, 23);
+ addChar(192, 0x3ffffe0, 26);
+ addChar(193, 0x3ffffe1, 26);
+ addChar(194, 0xfffeb, 20);
+ addChar(195, 0x7fff1, 19);
+ addChar(196, 0x3fffe7, 22);
+ addChar(197, 0x7ffff2, 23);
+ addChar(198, 0x3fffe8, 22);
+ addChar(199, 0x1ffffec, 25);
+ addChar(200, 0x3ffffe2, 26);
+ addChar(201, 0x3ffffe3, 26);
+ addChar(202, 0x3ffffe4, 26);
+ addChar(203, 0x7ffffde, 27);
+ addChar(204, 0x7ffffdf, 27);
+ addChar(205, 0x3ffffe5, 26);
+ addChar(206, 0xfffff1, 24);
+ addChar(207, 0x1ffffed, 25);
+ addChar(208, 0x7fff2, 19);
+ addChar(209, 0x1fffe3, 21);
+ addChar(210, 0x3ffffe6, 26);
+ addChar(211, 0x7ffffe0, 27);
+ addChar(212, 0x7ffffe1, 27);
+ addChar(213, 0x3ffffe7, 26);
+ addChar(214, 0x7ffffe2, 27);
+ addChar(215, 0xfffff2, 24);
+ addChar(216, 0x1fffe4, 21);
+ addChar(217, 0x1fffe5, 21);
+ addChar(218, 0x3ffffe8, 26);
+ addChar(219, 0x3ffffe9, 26);
+ addChar(220, 0xffffffd, 28);
+ addChar(221, 0x7ffffe3, 27);
+ addChar(222, 0x7ffffe4, 27);
+ addChar(223, 0x7ffffe5, 27);
+ addChar(224, 0xfffec, 20);
+ addChar(225, 0xfffff3, 24);
+ addChar(226, 0xfffed, 20);
+ addChar(227, 0x1fffe6, 21);
+ addChar(228, 0x3fffe9, 22);
+ addChar(229, 0x1fffe7, 21);
+ addChar(230, 0x1fffe8, 21);
+ addChar(231, 0x7ffff3, 23);
+ addChar(232, 0x3fffea, 22);
+ addChar(233, 0x3fffeb, 22);
+ addChar(234, 0x1ffffee, 25);
+ addChar(235, 0x1ffffef, 25);
+ addChar(236, 0xfffff4, 24);
+ addChar(237, 0xfffff5, 24);
+ addChar(238, 0x3ffffea, 26);
+ addChar(239, 0x7ffff4, 23);
+ addChar(240, 0x3ffffeb, 26);
+ addChar(241, 0x7ffffe6, 27);
+ addChar(242, 0x3ffffec, 26);
+ addChar(243, 0x3ffffed, 26);
+ addChar(244, 0x7ffffe7, 27);
+ addChar(245, 0x7ffffe8, 27);
+ addChar(246, 0x7ffffe9, 27);
+ addChar(247, 0x7ffffea, 27);
+ addChar(248, 0x7ffffeb, 27);
+ addChar(249, 0xffffffe, 28);
+ addChar(250, 0x7ffffec, 27);
+ addChar(251, 0x7ffffed, 27);
+ addChar(252, 0x7ffffee, 27);
+ addChar(253, 0x7ffffef, 27);
+ addChar(254, 0x7fffff0, 27);
+ addChar(255, 0x3ffffee, 26);
+ addEOS (256, EOS.code, EOS.length);
+ // @formatter:on
+ }
+
+
+ /**
+ * Calculates the number of bytes required to represent the given {@code
+ * CharSequence} with the Huffman coding.
+ *
+ * @param value
+ * characters
+ *
+ * @return number of bytes
+ *
+ * @throws NullPointerException
+ * if the value is null
+ */
+ public int lengthOf(CharSequence value) {
+ return lengthOf(value, 0, value.length());
+ }
+
+ /**
+ * Calculates the number of bytes required to represent a subsequence of the
+ * given {@code CharSequence} with the Huffman coding.
+ *
+ * @param value
+ * characters
+ * @param start
+ * the start index, inclusive
+ * @param end
+ * the end index, exclusive
+ *
+ * @return number of bytes
+ *
+ * @throws NullPointerException
+ * if the value is null
+ * @throws IndexOutOfBoundsException
+ * if any invocation of {@code value.charAt(i)}, where {@code start
+ * <= i < end} would throw an IndexOutOfBoundsException
+ */
+ public int lengthOf(CharSequence value, int start, int end) {
+ int len = 0;
+ for (int i = start; i < end; i++) {
+ char c = value.charAt(i);
+ len += INSTANCE.codeOf(c).length;
+ }
+ // Integer division with ceiling, assumption:
+ assert (len / 8 + (len % 8 != 0 ? 1 : 0)) == (len + 7) / 8 : len;
+ return (len + 7) / 8;
+ }
+
+ private void addChar(int c, int code, int bitLength) {
+ addLeaf(c, code, bitLength, false);
+ codes[c] = new Code(code, bitLength);
+ }
+
+ private void addEOS(int c, int code, int bitLength) {
+ addLeaf(c, code, bitLength, true);
+ codes[c] = new Code(code, bitLength);
+ }
+
+ private void addLeaf(int c, int code, int bitLength, boolean isEOS) {
+ if (bitLength < 1) {
+ throw new IllegalArgumentException("bitLength < 1");
+ }
+ Node curr = root;
+ for (int p = 1 << bitLength - 1; p != 0 && !curr.isLeaf(); p = p >> 1) {
+ curr.isEOSPath |= isEOS; // If it's already true, it can't become false
+ curr = curr.addChildIfAbsent(p & code);
+ }
+ curr.isEOSPath |= isEOS; // The last one needs to have this property as well
+ if (curr.isLeaf()) {
+ throw new IllegalStateException("Specified code is already taken");
+ }
+ curr.setChar((char) c);
+ }
+
+ private Code codeOf(char c) {
+ if (c > 255) {
+ throw new IllegalArgumentException("char=" + ((int) c));
+ }
+ return codes[c];
+ }
+
+ //
+ // For debugging/testing purposes
+ //
+ Node getRoot() {
+ return root;
+ }
+
+ //
+ // Guarantees:
+ //
+ // if (isLeaf() == true) => getChar() is a legal call
+ // if (isLeaf() == false) => getChild(i) is a legal call (though it can
+ // return null)
+ //
+ static class Node {
+
+ Node left;
+ Node right;
+ boolean isEOSPath;
+
+ boolean charIsSet;
+ char c;
+
+ Node getChild(int selector) {
+ if (isLeaf()) {
+ throw new IllegalStateException("This is a leaf node");
+ }
+ Node result = selector == 0 ? left : right;
+ if (result == null) {
+ throw new IllegalStateException(format(
+ "Node doesn't have a child (selector=%s)", selector));
+ }
+ return result;
+ }
+
+ boolean isLeaf() {
+ return charIsSet;
+ }
+
+ char getChar() {
+ if (!isLeaf()) {
+ throw new IllegalStateException("This node is not a leaf node");
+ }
+ return c;
+ }
+
+ void setChar(char c) {
+ if (charIsSet) {
+ throw new IllegalStateException(
+ "This node has been taken already");
+ }
+ if (left != null || right != null) {
+ throw new IllegalStateException("The node cannot be made "
+ + "a leaf as it's already has a child");
+ }
+ this.c = c;
+ charIsSet = true;
+ }
+
+ Node addChildIfAbsent(int i) {
+ if (charIsSet) {
+ throw new IllegalStateException("The node cannot have a child "
+ + "as it's already a leaf node");
+ }
+ Node child;
+ if (i == 0) {
+ if ((child = left) == null) {
+ child = left = new Node();
+ }
+ } else {
+ if ((child = right) == null) {
+ child = right = new Node();
+ }
+ }
+ return child;
+ }
+
+ @Override
+ public String toString() {
+ if (isLeaf()) {
+ if (isEOSPath) {
+ return "EOS";
+ } else {
+ return format("char: (%3s) '%s'", (int) c, c);
+ }
+ }
+ return "/\\";
+ }
+ }
+
+ // TODO: value-based class?
+ // FIXME: can we re-use Node instead of this class?
+ private static final class Code {
+
+ final int code;
+ final int length;
+
+ private Code(int code, int length) {
+ this.code = code;
+ this.length = length;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public int getLength() {
+ return length;
+ }
+
+ @Override
+ public String toString() {
+ long p = 1 << length;
+ return Long.toBinaryString(code + p).substring(1)
+ + ", length=" + length;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/ISO_8859_1.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2015, 2016, 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.net.httpclient.hpack;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.ByteBuffer;
+
+//
+// Custom implementation of ISO/IEC 8859-1:1998
+//
+// The rationale behind this is not to deal with CharsetEncoder/CharsetDecoder,
+// basically because it would require wrapping every single CharSequence into a
+// CharBuffer and then copying it back.
+//
+// But why not to give a CharBuffer instead of Appendable? Because I can choose
+// an Appendable (e.g. StringBuilder) that adjusts its length when needed and
+// therefore not to deal with pre-sized CharBuffers or copying.
+//
+// The encoding is simple and well known: 1 byte <-> 1 char
+//
+final class ISO_8859_1 {
+
+ private ISO_8859_1() { }
+
+ public static final class Reader {
+
+ public void read(ByteBuffer source, Appendable destination) {
+ for (int i = 0, len = source.remaining(); i < len; i++) {
+ char c = (char) (source.get() & 0xff);
+ try {
+ destination.append(c);
+ } catch (IOException e) {
+ throw new UncheckedIOException
+ ("Error appending to the destination", e);
+ }
+ }
+ }
+
+ public Reader reset() {
+ return this;
+ }
+ }
+
+ public static final class Writer {
+
+ private CharSequence source;
+ private int pos;
+ private int end;
+
+ public Writer configure(CharSequence source, int start, int end) {
+ this.source = source;
+ this.pos = start;
+ this.end = end;
+ return this;
+ }
+
+ public boolean write(ByteBuffer destination) {
+ for (; pos < end; pos++) {
+ char c = source.charAt(pos);
+ if (c > '\u00FF') {
+ throw new IllegalArgumentException(
+ "Illegal ISO-8859-1 char: " + (int) c);
+ }
+ if (destination.hasRemaining()) {
+ destination.put((byte) c);
+ } else {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public Writer reset() {
+ source = null;
+ pos = -1;
+ end = -1;
+ return this;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IndexNameValueWriter.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2015, 2016, 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.net.httpclient.hpack;
+
+import java.nio.ByteBuffer;
+
+abstract class IndexNameValueWriter implements BinaryRepresentationWriter {
+
+ private final int pattern;
+ private final int prefix;
+ private final IntegerWriter intWriter = new IntegerWriter();
+ private final StringWriter nameWriter = new StringWriter();
+ private final StringWriter valueWriter = new StringWriter();
+
+ protected boolean indexedRepresentation;
+
+ private static final int NEW = 0;
+ private static final int NAME_PART_WRITTEN = 1;
+ private static final int VALUE_WRITTEN = 2;
+
+ private int state = NEW;
+
+ protected IndexNameValueWriter(int pattern, int prefix) {
+ this.pattern = pattern;
+ this.prefix = prefix;
+ }
+
+ IndexNameValueWriter index(int index) {
+ indexedRepresentation = true;
+ intWriter.configure(index, prefix, pattern);
+ return this;
+ }
+
+ IndexNameValueWriter name(CharSequence name, boolean useHuffman) {
+ indexedRepresentation = false;
+ intWriter.configure(0, prefix, pattern);
+ nameWriter.configure(name, useHuffman);
+ return this;
+ }
+
+ IndexNameValueWriter value(CharSequence value, boolean useHuffman) {
+ valueWriter.configure(value, useHuffman);
+ return this;
+ }
+
+ @Override
+ public boolean write(HeaderTable table, ByteBuffer destination) {
+ if (state < NAME_PART_WRITTEN) {
+ if (indexedRepresentation) {
+ if (!intWriter.write(destination)) {
+ return false;
+ }
+ } else {
+ if (!intWriter.write(destination) || !nameWriter.write(destination)) {
+ return false;
+ }
+ }
+ state = NAME_PART_WRITTEN;
+ }
+ if (state < VALUE_WRITTEN) {
+ if (!valueWriter.write(destination)) {
+ return false;
+ }
+ state = VALUE_WRITTEN;
+ }
+ return state == VALUE_WRITTEN;
+ }
+
+ @Override
+ public IndexNameValueWriter reset() {
+ intWriter.reset();
+ if (!indexedRepresentation) {
+ nameWriter.reset();
+ }
+ valueWriter.reset();
+ state = NEW;
+ return this;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IndexedWriter.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015, 2016, 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.net.httpclient.hpack;
+
+import java.nio.ByteBuffer;
+
+final class IndexedWriter implements BinaryRepresentationWriter {
+
+ private final IntegerWriter intWriter = new IntegerWriter();
+
+ IndexedWriter() { }
+
+ IndexedWriter index(int index) {
+ intWriter.configure(index, 7, 0b1000_0000);
+ return this;
+ }
+
+ @Override
+ public boolean write(HeaderTable table, ByteBuffer destination) {
+ return intWriter.write(destination);
+ }
+
+ @Override
+ public BinaryRepresentationWriter reset() {
+ intWriter.reset();
+ return this;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IntegerReader.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2014, 2016, 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.net.httpclient.hpack;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+import static java.lang.String.format;
+
+final class IntegerReader {
+
+ private static final int NEW = 0;
+ private static final int CONFIGURED = 1;
+ private static final int FIRST_BYTE_READ = 2;
+ private static final int DONE = 4;
+
+ private int state = NEW;
+
+ private int N;
+ private int maxValue;
+ private int value;
+ private long r;
+ private long b = 1;
+
+ public IntegerReader configure(int N) {
+ return configure(N, Integer.MAX_VALUE);
+ }
+
+ //
+ // Why is it important to configure 'maxValue' here. After all we can wait
+ // for the integer to be fully read and then check it. Can't we?
+ //
+ // Two reasons.
+ //
+ // 1. Value wraps around long won't be unnoticed.
+ // 2. It can spit out an exception as soon as it becomes clear there's
+ // an overflow. Therefore, no need to wait for the value to be fully read.
+ //
+ public IntegerReader configure(int N, int maxValue) {
+ if (state != NEW) {
+ throw new IllegalStateException("Already configured");
+ }
+ checkPrefix(N);
+ if (maxValue < 0) {
+ throw new IllegalArgumentException(
+ "maxValue >= 0: maxValue=" + maxValue);
+ }
+ this.maxValue = maxValue;
+ this.N = N;
+ state = CONFIGURED;
+ return this;
+ }
+
+ public boolean read(ByteBuffer input) {
+ if (state == NEW) {
+ throw new IllegalStateException("Configure first");
+ }
+ if (state == DONE) {
+ return true;
+ }
+ if (!input.hasRemaining()) {
+ return false;
+ }
+ if (state == CONFIGURED) {
+ int max = (2 << (N - 1)) - 1;
+ int n = input.get() & max;
+ if (n != max) {
+ value = n;
+ state = DONE;
+ return true;
+ } else {
+ r = max;
+ }
+ state = FIRST_BYTE_READ;
+ }
+ if (state == FIRST_BYTE_READ) {
+ // variable-length quantity (VLQ)
+ byte i;
+ do {
+ if (!input.hasRemaining()) {
+ return false;
+ }
+ i = input.get();
+ long increment = b * (i & 127);
+ if (r + increment > maxValue) {
+ throw new IllegalArgumentException(format(
+ "Integer overflow: maxValue=%,d, value=%,d",
+ maxValue, r + increment));
+ }
+ r += increment;
+ b *= 128;
+ } while ((128 & i) == 128);
+
+ value = (int) r;
+ state = DONE;
+ return true;
+ }
+ throw new InternalError(Arrays.toString(
+ new Object[]{state, N, maxValue, value, r, b}));
+ }
+
+ public int get() throws IllegalStateException {
+ if (state != DONE) {
+ throw new IllegalStateException("Has not been fully read yet");
+ }
+ return value;
+ }
+
+ private static void checkPrefix(int N) {
+ if (N < 1 || N > 8) {
+ throw new IllegalArgumentException("1 <= N <= 8: N= " + N);
+ }
+ }
+
+ public IntegerReader reset() {
+ b = 1;
+ state = NEW;
+ return this;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IntegerWriter.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2015, 2016, 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.net.httpclient.hpack;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+final class IntegerWriter {
+
+ private static final int NEW = 0;
+ private static final int CONFIGURED = 1;
+ private static final int FIRST_BYTE_WRITTEN = 2;
+ private static final int DONE = 4;
+
+ private int state = NEW;
+
+ private int payload;
+ private int N;
+ private int value;
+
+ //
+ // 0 1 2 3 4 5 6 7
+ // +---+---+---+---+---+---+---+---+
+ // | | | | | | | | |
+ // +---+---+---+-------------------+
+ // |<--------->|<----------------->|
+ // payload N=5
+ //
+ // payload is the contents of the left-hand side part of the octet;
+ // it is truncated to fit into 8-N bits, where 1 <= N <= 8;
+ //
+ public IntegerWriter configure(int value, int N, int payload) {
+ if (state != NEW) {
+ throw new IllegalStateException("Already configured");
+ }
+ if (value < 0) {
+ throw new IllegalArgumentException("value >= 0: value=" + value);
+ }
+ checkPrefix(N);
+ this.value = value;
+ this.N = N;
+ this.payload = payload & 0xFF & (0xFFFFFFFF << N);
+ state = CONFIGURED;
+ return this;
+ }
+
+ public boolean write(ByteBuffer output) {
+ if (state == NEW) {
+ throw new IllegalStateException("Configure first");
+ }
+ if (state == DONE) {
+ return true;
+ }
+
+ if (!output.hasRemaining()) {
+ return false;
+ }
+ if (state == CONFIGURED) {
+ int max = (2 << (N - 1)) - 1;
+ if (value < max) {
+ output.put((byte) (payload | value));
+ state = DONE;
+ return true;
+ }
+ output.put((byte) (payload | max));
+ value -= max;
+ state = FIRST_BYTE_WRITTEN;
+ }
+ if (state == FIRST_BYTE_WRITTEN) {
+ while (value >= 128 && output.hasRemaining()) {
+ output.put((byte) (value % 128 + 128));
+ value /= 128;
+ }
+ if (!output.hasRemaining()) {
+ return false;
+ }
+ output.put((byte) value);
+ state = DONE;
+ return true;
+ }
+ throw new InternalError(Arrays.toString(
+ new Object[]{state, payload, N, value}));
+ }
+
+ private static void checkPrefix(int N) {
+ if (N < 1 || N > 8) {
+ throw new IllegalArgumentException("1 <= N <= 8: N= " + N);
+ }
+ }
+
+ public IntegerWriter reset() {
+ state = NEW;
+ return this;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/LiteralNeverIndexedWriter.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015, 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.net.httpclient.hpack;
+
+final class LiteralNeverIndexedWriter extends IndexNameValueWriter {
+
+ LiteralNeverIndexedWriter() {
+ super(0b0001_0000, 4);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/LiteralWithIndexingWriter.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2015, 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.net.httpclient.hpack;
+
+import java.nio.ByteBuffer;
+
+final class LiteralWithIndexingWriter extends IndexNameValueWriter {
+
+ private boolean tableUpdated;
+
+ private CharSequence name;
+ private CharSequence value;
+ private int index;
+
+ LiteralWithIndexingWriter() {
+ super(0b0100_0000, 6);
+ }
+
+ @Override
+ LiteralWithIndexingWriter index(int index) {
+ super.index(index);
+ this.index = index;
+ return this;
+ }
+
+ @Override
+ LiteralWithIndexingWriter name(CharSequence name, boolean useHuffman) {
+ super.name(name, useHuffman);
+ this.name = name;
+ return this;
+ }
+
+ @Override
+ LiteralWithIndexingWriter value(CharSequence value, boolean useHuffman) {
+ super.value(value, useHuffman);
+ this.value = value;
+ return this;
+ }
+
+ @Override
+ public boolean write(HeaderTable table, ByteBuffer destination) {
+ if (!tableUpdated) {
+ CharSequence n;
+ if (indexedRepresentation) {
+ n = table.get(index).name;
+ } else {
+ n = name;
+ }
+ table.put(n, value);
+ tableUpdated = true;
+ }
+ return super.write(table, destination);
+ }
+
+ @Override
+ public IndexNameValueWriter reset() {
+ tableUpdated = false;
+ name = null;
+ value = null;
+ index = -1;
+ return super.reset();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/LiteralWriter.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015, 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.net.httpclient.hpack;
+
+final class LiteralWriter extends IndexNameValueWriter {
+
+ LiteralWriter() {
+ super(0b0000_0000, 4);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/SizeUpdateWriter.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015, 2016, 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.net.httpclient.hpack;
+
+import java.nio.ByteBuffer;
+
+final class SizeUpdateWriter implements BinaryRepresentationWriter {
+
+ private final IntegerWriter intWriter = new IntegerWriter();
+ private int maxSize;
+ private boolean tableUpdated;
+
+ SizeUpdateWriter() { }
+
+ SizeUpdateWriter maxHeaderTableSize(int size) {
+ intWriter.configure(size, 5, 0b0010_0000);
+ this.maxSize = size;
+ return this;
+ }
+
+ @Override
+ public boolean write(HeaderTable table, ByteBuffer destination) {
+ if (!tableUpdated) {
+ table.setMaxSize(maxSize);
+ tableUpdated = true;
+ }
+ return intWriter.write(destination);
+ }
+
+ @Override
+ public BinaryRepresentationWriter reset() {
+ intWriter.reset();
+ maxSize = -1;
+ tableUpdated = false;
+ return this;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/StringReader.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2015, 2016, 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.net.httpclient.hpack;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+//
+// 0 1 2 3 4 5 6 7
+// +---+---+---+---+---+---+---+---+
+// | H | String Length (7+) |
+// +---+---------------------------+
+// | String Data (Length octets) |
+// +-------------------------------+
+//
+final class StringReader {
+
+ private static final int NEW = 0;
+ private static final int FIRST_BYTE_READ = 1;
+ private static final int LENGTH_READ = 2;
+ private static final int DONE = 4;
+
+ private final IntegerReader intReader = new IntegerReader();
+ private final Huffman.Reader huffmanReader = new Huffman.Reader();
+ private final ISO_8859_1.Reader plainReader = new ISO_8859_1.Reader();
+
+ private int state = NEW;
+
+ private boolean huffman;
+ private int remainingLength;
+
+ boolean read(ByteBuffer input, Appendable output) {
+ if (state == DONE) {
+ return true;
+ }
+ if (!input.hasRemaining()) {
+ return false;
+ }
+ if (state == NEW) {
+ int p = input.position();
+ huffman = (input.get(p) & 0b10000000) != 0;
+ state = FIRST_BYTE_READ;
+ intReader.configure(7);
+ }
+ if (state == FIRST_BYTE_READ) {
+ boolean lengthRead = intReader.read(input);
+ if (!lengthRead) {
+ return false;
+ }
+ remainingLength = intReader.get();
+ state = LENGTH_READ;
+ }
+ if (state == LENGTH_READ) {
+ boolean isLast = input.remaining() >= remainingLength;
+ int oldLimit = input.limit();
+ if (isLast) {
+ input.limit(input.position() + remainingLength);
+ }
+ if (huffman) {
+ huffmanReader.read(input, output, isLast);
+ } else {
+ plainReader.read(input, output);
+ }
+ if (isLast) {
+ input.limit(oldLimit);
+ }
+ return isLast;
+ }
+ throw new InternalError(Arrays.toString(
+ new Object[]{state, huffman, remainingLength}));
+ }
+
+ boolean isHuffmanEncoded() {
+ if (state < FIRST_BYTE_READ) {
+ throw new IllegalStateException("Has not been fully read yet");
+ }
+ return huffman;
+ }
+
+ void reset() {
+ if (huffman) {
+ huffmanReader.reset();
+ } else {
+ plainReader.reset();
+ }
+ intReader.reset();
+ state = NEW;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/StringWriter.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2015, 2016, 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.net.httpclient.hpack;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+//
+// 0 1 2 3 4 5 6 7
+// +---+---+---+---+---+---+---+---+
+// | H | String Length (7+) |
+// +---+---------------------------+
+// | String Data (Length octets) |
+// +-------------------------------+
+//
+// StringWriter does not require a notion of endOfInput (isLast) in 'write'
+// methods due to the nature of string representation in HPACK. Namely, the
+// length of the string is put before string's contents. Therefore the length is
+// always known beforehand.
+//
+// Expected use:
+//
+// configure write* (reset configure write*)*
+//
+final class StringWriter {
+
+ private static final int NEW = 0;
+ private static final int CONFIGURED = 1;
+ private static final int LENGTH_WRITTEN = 2;
+ private static final int DONE = 4;
+
+ private final IntegerWriter intWriter = new IntegerWriter();
+ private final Huffman.Writer huffmanWriter = new Huffman.Writer();
+ private final ISO_8859_1.Writer plainWriter = new ISO_8859_1.Writer();
+
+ private int state = NEW;
+ private boolean huffman;
+
+ StringWriter configure(CharSequence input, boolean huffman) {
+ return configure(input, 0, input.length(), huffman);
+ }
+
+ StringWriter configure(CharSequence input, int start, int end,
+ boolean huffman) {
+ if (start < 0 || end < 0 || end > input.length() || start > end) {
+ throw new IndexOutOfBoundsException(
+ String.format("input.length()=%s, start=%s, end=%s",
+ input.length(), start, end));
+ }
+ if (!huffman) {
+ plainWriter.configure(input, start, end);
+ intWriter.configure(end - start, 7, 0b0000_0000);
+ } else {
+ huffmanWriter.from(input, start, end);
+ intWriter.configure(Huffman.INSTANCE.lengthOf(input, start, end),
+ 7, 0b1000_0000);
+ }
+
+ this.huffman = huffman;
+ state = CONFIGURED;
+ return this;
+ }
+
+ boolean write(ByteBuffer output) {
+ if (state == DONE) {
+ return true;
+ }
+ if (state == NEW) {
+ throw new IllegalStateException("Configure first");
+ }
+ if (!output.hasRemaining()) {
+ return false;
+ }
+ if (state == CONFIGURED) {
+ if (intWriter.write(output)) {
+ state = LENGTH_WRITTEN;
+ } else {
+ return false;
+ }
+ }
+ if (state == LENGTH_WRITTEN) {
+ boolean written = huffman
+ ? huffmanWriter.write(output)
+ : plainWriter.write(output);
+ if (written) {
+ state = DONE;
+ return true;
+ } else {
+ return false;
+ }
+ }
+ throw new InternalError(Arrays.toString(new Object[]{state, huffman}));
+ }
+
+ void reset() {
+ intWriter.reset();
+ if (huffman) {
+ huffmanWriter.reset();
+ } else {
+ plainWriter.reset();
+ }
+ state = NEW;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/package-info.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015, 2016, 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.
+ */
+/**
+ * HPACK (Header Compression for HTTP/2) implementation conforming to
+ * <a href="https://tools.ietf.org/html/rfc7541">RFC 7541</a>.
+ *
+ * <p> Headers can be decoded and encoded by {@link sun.net.httpclient.hpack.Decoder}
+ * and {@link sun.net.httpclient.hpack.Encoder} respectively.
+ *
+ * <p> Instances of these classes are not safe for use by multiple threads.
+ */
+package sun.net.httpclient.hpack;
--- a/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java Thu Apr 21 13:37:31 2016 -0700
@@ -42,7 +42,6 @@
import java.util.stream.Stream;
import jdk.internal.misc.JavaAWTAccess;
import jdk.internal.misc.SharedSecrets;
-import sun.misc.ManagedLocalsThread;
import sun.util.logging.internal.LoggingProviderImpl;
/**
@@ -254,9 +253,10 @@
// This private class is used as a shutdown hook.
// It does a "reset" to close all open handlers.
- private class Cleaner extends ManagedLocalsThread {
+ private class Cleaner extends Thread {
private Cleaner() {
+ super(null, null, "Logging-Cleaner", 0, false);
/* Set context class loader to null in order to avoid
* keeping a strong reference to an application classloader.
*/
--- a/jdk/src/java.logging/share/classes/module-info.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.logging/share/classes/module-info.java Thu Apr 21 13:37:31 2016 -0700
@@ -24,8 +24,6 @@
*/
module java.logging {
- // 8153158
- requires jdk.unsupported;
exports java.util.logging;
provides jdk.internal.logger.DefaultLoggerFinder with
sun.util.logging.internal.LoggingProviderImpl;
--- a/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientCommunicatorAdmin.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientCommunicatorAdmin.java Thu Apr 21 13:37:31 2016 -0700
@@ -30,7 +30,6 @@
import com.sun.jmx.remote.util.ClassLogger;
import com.sun.jmx.remote.util.EnvHelp;
-import sun.misc.ManagedLocalsThread;
public abstract class ClientCommunicatorAdmin {
private static volatile long threadNo = 1;
@@ -41,10 +40,11 @@
if (period > 0) {
checker = new Checker();
- Thread t = new ManagedLocalsThread(
- checker,
- "JMX client heartbeat " + (++threadNo)
- );
+ Thread t = new Thread(null,
+ checker,
+ "JMX client heartbeat " + (++threadNo),
+ 0,
+ false);
t.setDaemon(true);
t.start();
--- a/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java Thu Apr 21 13:37:31 2016 -0700
@@ -52,7 +52,6 @@
import com.sun.jmx.remote.util.ClassLogger;
import com.sun.jmx.remote.util.EnvHelp;
import java.rmi.UnmarshalException;
-import sun.misc.ManagedLocalsThread;
public abstract class ClientNotifForwarder {
@@ -91,7 +90,8 @@
throw new IllegalArgumentException("More than one command");
this.command = command;
if (thread == null) {
- thread = new ManagedLocalsThread(
+ thread = new Thread(
+ null,
()-> {
while (true) {
Runnable r;
@@ -107,7 +107,9 @@
r.run();
}
},
- "ClientNotifForwarder-" + ++threadId
+ "ClientNotifForwarder-" + ++threadId,
+ 0,
+ false
);
thread.setDaemon(true);
thread.start();
--- a/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ServerCommunicatorAdmin.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ServerCommunicatorAdmin.java Thu Apr 21 13:37:31 2016 -0700
@@ -27,7 +27,6 @@
import com.sun.jmx.remote.util.ClassLogger;
-import sun.misc.ManagedLocalsThread;
public abstract class ServerCommunicatorAdmin {
public ServerCommunicatorAdmin(long timeout) {
@@ -42,7 +41,11 @@
timestamp = 0;
if (timeout < Long.MAX_VALUE) {
Runnable timeoutTask = new Timeout();
- final Thread t = new ManagedLocalsThread(timeoutTask);
+ final Thread t = new Thread(null,
+ timeoutTask,
+ "JMX-Server-Admin-Timeout",
+ 0,
+ false);
t.setName("JMX server connection timeout " + t.getId());
// If you change this name you will need to change a unit test
// (NoServerTimeoutTest)
--- a/jdk/src/java.management/share/classes/javax/management/monitor/Monitor.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.management/share/classes/javax/management/monitor/Monitor.java Thu Apr 21 13:37:31 2016 -0700
@@ -61,7 +61,6 @@
import javax.management.ObjectName;
import javax.management.ReflectionException;
import static javax.management.monitor.MonitorNotification.*;
-import sun.misc.ManagedLocalsThread;
/**
* Defines the part common to all monitor MBeans.
@@ -1637,10 +1636,12 @@
}
public Thread newThread(Runnable r) {
- Thread t = new ManagedLocalsThread(
+ Thread t = new Thread(
group,
r,
- namePrefix + threadNumber.getAndIncrement() + nameSuffix
+ namePrefix + threadNumber.getAndIncrement() + nameSuffix,
+ 0,
+ false
);
t.setDaemon(true);
--- a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnectorServer.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnectorServer.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, 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
@@ -45,6 +45,7 @@
import javax.management.InstanceNotFoundException;
import javax.management.MBeanServer;
+import javax.management.remote.JMXAuthenticator;
import javax.management.remote.JMXConnectionNotification;
import javax.management.remote.JMXConnector;
@@ -100,6 +101,21 @@
"jmx.remote.rmi.server.socket.factory";
/**
+ * Name of the attribute that specifies a list of class names acceptable
+ * as parameters to the {@link RMIServer#newClient(java.lang.Object) RMIServer.newClient()}
+ * remote method call.
+ * <p>
+ * This list of classes should correspond to the transitive closure of the
+ * credentials class (or classes) used by the installed {@linkplain JMXAuthenticator}
+ * associated with the {@linkplain RMIServer} implementation.
+ * <p>
+ * If the attribute is not set, or is null, then any class is
+ * deemed acceptable.
+ */
+ public static final String CREDENTIAL_TYPES =
+ "jmx.remote.rmi.server.credential.types";
+
+ /**
* <p>Makes an <code>RMIConnectorServer</code>.
* This is equivalent to calling {@link #RMIConnectorServer(
* JMXServiceURL,Map,RMIServerImpl,MBeanServer)
--- a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIJRMPServerImpl.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIJRMPServerImpl.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, 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
@@ -39,6 +39,13 @@
import com.sun.jmx.remote.internal.RMIExporter;
import com.sun.jmx.remote.util.EnvHelp;
+import java.io.ObjectStreamClass;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import sun.reflect.misc.ReflectUtil;
+import sun.rmi.server.DeserializationChecker;
import sun.rmi.server.UnicastServerRef;
import sun.rmi.server.UnicastServerRef2;
@@ -52,6 +59,9 @@
* @since 1.5
*/
public class RMIJRMPServerImpl extends RMIServerImpl {
+
+ private final ExportedWrapper exportedWrapper;
+
/**
* <p>Creates a new {@link RMIServer} object that will be exported
* on the given port using the given socket factories.</p>
@@ -89,10 +99,31 @@
this.csf = csf;
this.ssf = ssf;
this.env = (env == null) ? Collections.<String, Object>emptyMap() : env;
+
+ String[] credentialsTypes
+ = (String[]) this.env.get(RMIConnectorServer.CREDENTIAL_TYPES);
+ List<String> types = null;
+ if (credentialsTypes != null) {
+ types = new ArrayList<>();
+ for (String type : credentialsTypes) {
+ if (type == null) {
+ throw new IllegalArgumentException("A credential type is null.");
+ }
+ ReflectUtil.checkPackageAccess(type);
+ types.add(type);
+ }
+ }
+ exportedWrapper = types != null ?
+ new ExportedWrapper(this, types) :
+ null;
}
protected void export() throws IOException {
- export(this);
+ if (exportedWrapper != null) {
+ export(exportedWrapper);
+ } else {
+ export(this);
+ }
}
private void export(Remote obj) throws RemoteException {
@@ -142,7 +173,11 @@
* RMIJRMPServerImpl has not been exported yet.
*/
public Remote toStub() throws IOException {
- return RemoteObject.toStub(this);
+ if (exportedWrapper != null) {
+ return RemoteObject.toStub(exportedWrapper);
+ } else {
+ return RemoteObject.toStub(this);
+ }
}
/**
@@ -189,11 +224,56 @@
* server failed.
*/
protected void closeServer() throws IOException {
- unexport(this, true);
+ if (exportedWrapper != null) {
+ unexport(exportedWrapper, true);
+ } else {
+ unexport(this, true);
+ }
}
private final int port;
private final RMIClientSocketFactory csf;
private final RMIServerSocketFactory ssf;
private final Map<String, ?> env;
+
+ private static class ExportedWrapper implements RMIServer, DeserializationChecker {
+ private final RMIServer impl;
+ private final List<String> allowedTypes;
+
+ private ExportedWrapper(RMIServer impl, List<String> credentialsTypes) {
+ this.impl = impl;
+ allowedTypes = credentialsTypes;
+ }
+
+ @Override
+ public String getVersion() throws RemoteException {
+ return impl.getVersion();
+ }
+
+ @Override
+ public RMIConnection newClient(Object credentials) throws IOException {
+ return impl.newClient(credentials);
+ }
+
+ @Override
+ public void check(Method method, ObjectStreamClass descriptor,
+ int paramIndex, int callID) {
+ String type = descriptor.getName();
+ if (!allowedTypes.contains(type)) {
+ throw new ClassCastException("Unsupported type: " + type);
+ }
+ }
+
+ @Override
+ public void checkProxyClass(Method method, String[] ifaces,
+ int paramIndex, int callID) {
+ if (ifaces != null && ifaces.length > 0) {
+ for (String iface : ifaces) {
+ if (!allowedTypes.contains(iface)) {
+ throw new ClassCastException("Unsupported type: " + iface);
+ }
+ }
+ }
+ }
+ }
}
--- a/jdk/src/java.management/share/classes/module-info.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.management/share/classes/module-info.java Thu Apr 21 13:37:31 2016 -0700
@@ -27,8 +27,6 @@
requires public java.rmi;
requires java.logging;
requires java.naming;
- // 8147553
- requires jdk.unsupported;
exports java.lang.management;
exports javax.management;
--- a/jdk/src/java.management/share/classes/sun/management/jdp/JdpController.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.management/share/classes/sun/management/jdp/JdpController.java Thu Apr 21 13:37:31 2016 -0700
@@ -34,7 +34,6 @@
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import sun.management.VMManagement;
-import sun.misc.ManagedLocalsThread;
/**
* JdpController is responsible to create and manage a broadcast loop.
@@ -219,7 +218,7 @@
controller = new JDPControllerRunner(bcast, packet, pause);
- Thread t = new ManagedLocalsThread(controller, "JDP broadcaster");
+ Thread t = new Thread(null, controller, "JDP broadcaster", 0, false);
t.setDaemon(true);
t.start();
}
--- a/jdk/src/java.management/share/classes/sun/management/jmxremote/ConnectorBootstrap.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.management/share/classes/sun/management/jmxremote/ConnectorBootstrap.java Thu Apr 21 13:37:31 2016 -0700
@@ -510,6 +510,9 @@
// This RMI server should not keep the VM alive
Map<String, Object> env = new HashMap<>();
env.put(RMIExporter.EXPORTER_ATTRIBUTE, new PermanentExporter());
+ env.put(RMIConnectorServer.CREDENTIAL_TYPES, new String[]{
+ String[].class.getName(), String.class.getName()
+ });
// The local connector server need only be available via the
// loopback connection.
@@ -740,6 +743,9 @@
PermanentExporter exporter = new PermanentExporter();
env.put(RMIExporter.EXPORTER_ATTRIBUTE, exporter);
+ env.put(RMIConnectorServer.CREDENTIAL_TYPES, new String[]{
+ String[].class.getName(), String.class.getName()
+ });
boolean useSocketFactory = bindAddress != null && !useSsl;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.rmi/share/classes/sun/rmi/server/DeserializationChecker.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2016, 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.rmi.server;
+
+import java.io.ObjectStreamClass;
+import java.lang.reflect.Method;
+
+/**
+ * Implementing this interface to have a deserialization control when RMI
+ * dispatches a remote request. If an exported object implements this interface,
+ * RMI dispatching mechanism will call the method {@code check} every time
+ * deserialising a remote object for invoking a method of the exported object.
+ *
+ * @author sjiang
+ */
+public interface DeserializationChecker {
+ /**
+ * Will be called to check a descriptor.
+ * This method may be called 2 times, the first time is when a descriptor is read
+ * from the stream, the second is just before creating an object described
+ * by this descriptor.
+ *
+ * @param method the method invoked from a remote request.
+ * @param descriptor The descriptor of the class of any object deserialised
+ * while deserialising the parameter. The first descriptor will be that of
+ * the top level object (the concrete class of the parameter itself);
+ * Subsequent calls with the same {@code method}, {@code paramIndex} and
+ * {@code callID} will correspond to objects contained in the parameter.
+ * @param paramIndex an index indicates the position of a parameter in the
+ * method. This index will be reused for deserialising all
+ * objects contained in the parameter object. For example, the parameter
+ * being deserialised is a {@code List}, all deserialisation calls for its
+ * elements will have same index.
+ * @param callID a unique ID identifying one
+ * time method invocation, the same ID is used for deserialization call of
+ * all parameters within the method.
+ */
+ public void check(Method method,
+ ObjectStreamClass descriptor,
+ int paramIndex,
+ int callID);
+
+ /**
+ * Will be called to validate a Proxy interfaces from a remote user before loading it.
+ * @param method the method invoked from a remote request.
+ * @param ifaces a string table of all interfaces implemented by the proxy to be checked.
+ * @param paramIndex an index indicates the position of a parameter in the
+ * method. This index will be reused for deserialising all
+ * objects contained in the parameter object. For example, the parameter
+ * being deserialised is a {@code List}, all deserialisation calls for its
+ * elements will have same index.
+ * @param callID a unique ID identifying one
+ * time method invocation, the same ID is used for deserialization call of
+ * all parameters within the method.
+ */
+ public void checkProxyClass(Method method,
+ String[] ifaces,
+ int paramIndex,
+ int callID);
+
+ /**
+ * Inform of the completion of parameter deserialisation for a method invocation.
+ * This is useful if the last parameter is a complex object, like a {@code List}
+ * which elements are complex object too.
+ *
+ * The default implementation does nothing.
+ * @param callID the ID identifying a method invocation.
+ */
+ public default void end(int callID) {}
+}
--- a/jdk/src/java.rmi/share/classes/sun/rmi/server/MarshalInputStream.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.rmi/share/classes/sun/rmi/server/MarshalInputStream.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, 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,13 +30,13 @@
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;
import java.io.StreamCorruptedException;
-import java.net.URL;
import java.util.*;
import java.security.AccessControlException;
import java.security.Permission;
-
import java.rmi.server.RMIClassLoader;
import java.security.PrivilegedAction;
+import jdk.internal.misc.ObjectStreamClassValidator;
+import jdk.internal.misc.SharedSecrets;
/**
* MarshalInputStream is an extension of ObjectInputStream. When resolving
@@ -54,6 +54,11 @@
* @author Peter Jones
*/
public class MarshalInputStream extends ObjectInputStream {
+ interface StreamChecker extends ObjectStreamClassValidator {
+ void checkProxyInterfaceNames(String[] ifaces);
+ }
+
+ private volatile StreamChecker streamChecker = null;
/**
* Value of "java.rmi.server.useCodebaseOnly" property,
@@ -123,7 +128,7 @@
throws IOException, StreamCorruptedException
{
super(in);
- }
+ }
/**
* Returns a callback previously registered via the setDoneCallback
@@ -240,6 +245,11 @@
protected Class<?> resolveProxyClass(String[] interfaces)
throws IOException, ClassNotFoundException
{
+ StreamChecker checker = streamChecker;
+ if (checker != null) {
+ checker.checkProxyInterfaceNames(interfaces);
+ }
+
/*
* Always read annotation written by MarshalOutputStream.
*/
@@ -319,4 +329,28 @@
void useCodebaseOnly() {
useCodebaseOnly = true;
}
+
+ synchronized void setStreamChecker(StreamChecker checker) {
+ streamChecker = checker;
+ SharedSecrets.getJavaObjectInputStreamAccess().setValidator(this, checker);
+ }
+ @Override
+ protected ObjectStreamClass readClassDescriptor() throws IOException,
+ ClassNotFoundException {
+ ObjectStreamClass descriptor = super.readClassDescriptor();
+
+ validateDesc(descriptor);
+
+ return descriptor;
+ }
+
+ private void validateDesc(ObjectStreamClass descriptor) {
+ StreamChecker checker;
+ synchronized (this) {
+ checker = streamChecker;
+ }
+ if (checker != null) {
+ checker.validateDescriptor(descriptor);
+ }
+ }
}
--- a/jdk/src/java.rmi/share/classes/sun/rmi/server/UnicastServerRef.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.rmi/share/classes/sun/rmi/server/UnicastServerRef.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, 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
@@ -28,7 +28,7 @@
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
-import java.io.PrintStream;
+import java.io.ObjectStreamClass;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.rmi.MarshalException;
@@ -52,6 +52,7 @@
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
import sun.rmi.runtime.Log;
import sun.rmi.transport.LiveRef;
import sun.rmi.transport.Target;
@@ -116,6 +117,8 @@
private static final Map<Class<?>,?> withoutSkeletons =
Collections.synchronizedMap(new WeakHashMap<Class<?>,Void>());
+ private final AtomicInteger methodCallIDCount = new AtomicInteger(0);
+
/**
* Create a new (empty) Unicast server remote reference.
*/
@@ -297,14 +300,11 @@
logCall(obj, method);
// unmarshal parameters
- Class<?>[] types = method.getParameterTypes();
- Object[] params = new Object[types.length];
+ Object[] params = null;
try {
unmarshalCustomCallData(in);
- for (int i = 0; i < types.length; i++) {
- params[i] = unmarshalValue(types[i], in);
- }
+ params = unmarshalParameters(obj, method, marshalStream);
} catch (java.io.IOException e) {
throw new UnmarshalException(
"error unmarshalling arguments", e);
@@ -565,4 +565,85 @@
return map;
}
}
+
+ /**
+ * Unmarshal parameters for the given method of the given instance over
+ * the given marshalinputstream. Perform any necessary checks.
+ */
+ private Object[] unmarshalParameters(Object obj, Method method, MarshalInputStream in)
+ throws IOException, ClassNotFoundException {
+ return (obj instanceof DeserializationChecker) ?
+ unmarshalParametersChecked((DeserializationChecker)obj, method, in) :
+ unmarshalParametersUnchecked(method, in);
+ }
+
+ /**
+ * Unmarshal parameters for the given method of the given instance over
+ * the given marshalinputstream. Do not perform any additional checks.
+ */
+ private Object[] unmarshalParametersUnchecked(Method method, ObjectInput in)
+ throws IOException, ClassNotFoundException {
+ Class<?>[] types = method.getParameterTypes();
+ Object[] params = new Object[types.length];
+ for (int i = 0; i < types.length; i++) {
+ params[i] = unmarshalValue(types[i], in);
+ }
+ return params;
+ }
+
+ /**
+ * Unmarshal parameters for the given method of the given instance over
+ * the given marshalinputstream. Do perform all additional checks.
+ */
+ private Object[] unmarshalParametersChecked(
+ DeserializationChecker checker,
+ Method method, MarshalInputStream in)
+ throws IOException, ClassNotFoundException {
+ int callID = methodCallIDCount.getAndIncrement();
+ MyChecker myChecker = new MyChecker(checker, method, callID);
+ in.setStreamChecker(myChecker);
+ try {
+ Class<?>[] types = method.getParameterTypes();
+ Object[] values = new Object[types.length];
+ for (int i = 0; i < types.length; i++) {
+ myChecker.setIndex(i);
+ values[i] = unmarshalValue(types[i], in);
+ }
+ myChecker.end(callID);
+ return values;
+ } finally {
+ in.setStreamChecker(null);
+ }
+ }
+
+ private static class MyChecker implements MarshalInputStream.StreamChecker {
+ private final DeserializationChecker descriptorCheck;
+ private final Method method;
+ private final int callID;
+ private int parameterIndex;
+
+ MyChecker(DeserializationChecker descriptorCheck, Method method, int callID) {
+ this.descriptorCheck = descriptorCheck;
+ this.method = method;
+ this.callID = callID;
+ }
+
+ @Override
+ public void validateDescriptor(ObjectStreamClass descriptor) {
+ descriptorCheck.check(method, descriptor, parameterIndex, callID);
+ }
+
+ @Override
+ public void checkProxyInterfaceNames(String[] ifaces) {
+ descriptorCheck.checkProxyClass(method, ifaces, parameterIndex, callID);
+ }
+
+ void setIndex(int parameterIndex) {
+ this.parameterIndex = parameterIndex;
+ }
+
+ void end(int callId) {
+ descriptorCheck.end(callId);
+ }
+ }
}
--- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/SunProvider.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/SunProvider.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, 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
@@ -97,8 +97,6 @@
}
}
- public static final SunProvider INSTANCE = new SunProvider();
-
public SunProvider() {
/* We are the Sun JGSS provider */
super("SunJGSS", 9.0d, INFO);
--- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSNameElement.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSNameElement.java Thu Apr 21 13:37:31 2016 -0700
@@ -159,7 +159,9 @@
int atPos = krbName.lastIndexOf('@');
if (atPos != -1) {
String atRealm = krbName.substring(atPos);
- if (nameType.equals(GSSUtil.NT_GSS_KRB5_PRINCIPAL)
+ // getNativeNameType() can modify NT_GSS_KRB5_PRINCIPAL to null
+ if ((nameType == null
+ || nameType.equals(GSSUtil.NT_GSS_KRB5_PRINCIPAL))
&& new String(nameBytes).endsWith(atRealm)) {
// Created from Kerberos name with realm, no need to check
} else {
--- a/jdk/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Klist.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Klist.java Thu Apr 21 13:37:31 2016 -0700
@@ -134,7 +134,7 @@
Character arg;
for (int i = 0; i < args.length; i++) {
if ((args[i].length() >= 2) && (args[i].startsWith("-"))) {
- arg = new Character(args[i].charAt(1));
+ arg = Character.valueOf(args[i].charAt(1));
switch (arg.charValue()) {
case 'c':
action = 'c';
--- a/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/CachedRowSetImpl.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/CachedRowSetImpl.java Thu Apr 21 13:37:31 2016 -0700
@@ -1963,7 +1963,7 @@
return (float)0;
}
try {
- return ((new Float(value.toString())).floatValue());
+ return Float.parseFloat(value.toString());
} catch (NumberFormatException ex) {
throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.floatfail").toString(),
new Object[] {value.toString().trim(), columnIndex}));
@@ -2007,7 +2007,7 @@
return (double)0;
}
try {
- return ((new Double(value.toString().trim())).doubleValue());
+ return Double.parseDouble(value.toString().trim());
} catch (NumberFormatException ex) {
throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.doublefail").toString(),
new Object[] {value.toString().trim(), columnIndex}));
@@ -4017,9 +4017,9 @@
return new BigDecimal(srcObj.toString().trim());
case java.sql.Types.REAL:
case java.sql.Types.FLOAT:
- return new Float(srcObj.toString().trim());
+ return Float.valueOf(srcObj.toString().trim());
case java.sql.Types.DOUBLE:
- return new Double(srcObj.toString().trim());
+ return Double.valueOf(srcObj.toString().trim());
case java.sql.Types.CHAR:
case java.sql.Types.VARCHAR:
case java.sql.Types.LONGVARCHAR:
--- a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, 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
@@ -26,13 +26,11 @@
package com.sun.java.accessibility.util;
-import java.lang.*;
+import com.sun.java.accessibility.util.internal.*;
import java.beans.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
-import java.awt.image.*;
-import java.security.AccessControlException;
// Do not import Swing classes. This module is intended to work
// with both Swing and AWT.
// import javax.swing.*;
@@ -77,12 +75,26 @@
if (c == null) {
return null;
}
- try {
- t = Class.forName("com.sun.java.accessibility.util.internal."
- + c.getSimpleName()
- + "Translator");
+ switch (c.getSimpleName()) {
+ case "Button":
+ t = ButtonTranslator.class;
+ break;
+ case "Checkbox":
+ t = CheckboxTranslator.class;
+ break;
+ case "Label":
+ t = LabelTranslator.class;
+ break;
+ case "List":
+ t = ListTranslator.class;
+ break;
+ case "TextComponent":
+ t = TextComponentTranslator.class;
+ break;
+ }
+ if (t != null) {
return t;
- } catch (Exception e) {
+ } else {
return getTranslatorClass(c.getSuperclass());
}
}
@@ -106,10 +118,6 @@
if (o instanceof Accessible) {
a = (Accessible)o;
} else {
- // About to "newInstance" an object of a class of a restricted package
- // so ensure the caller is allowed access to that package.
- String pkg = "com.sun.java.accessibility.util.internal";
- System.getSecurityManager().checkPackageAccess(pkg);
Class<?> translatorClass = getTranslatorClass(o.getClass());
if (translatorClass != null) {
try {
--- a/jdk/src/jdk.accessibility/windows/native/jaccesswalker/jaccesswalker.cpp Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/jdk.accessibility/windows/native/jaccesswalker/jaccesswalker.cpp Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, 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
@@ -543,7 +543,7 @@
} else {
char s[LINE_BUFSIZE];
sprintf( s,
- "ERROR calling GetAccessibleContextInfo; vmID = %X, context = %X",
+ "ERROR calling GetAccessibleContextInfo; vmID = %X, context = %p",
vmID, context );
TVITEM tvi;
--- a/jdk/src/jdk.accessibility/windows/native/libwindowsaccessbridge/WinAccessBridge.cpp Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/jdk.accessibility/windows/native/libwindowsaccessbridge/WinAccessBridge.cpp Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, 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
@@ -1125,7 +1125,7 @@
PrintDebugString("WinAccessBridge::getAccessibleContextWithFocus(%p, %X, )", window, vmID);
// find vmID, etc. from HWND; ask that VM for the AC w/Focus
- HWND pkgVMID = (HWND)ABLongToHandle( pkg->rVMID ) ;
+ HWND pkgVMID;
if (getAccessibleContextFromHWND(window, (long *)&(pkgVMID), &(pkg->rAccessibleContext)) == TRUE) {
HWND destABWindow = javaVMs->findAccessBridgeWindow((long)pkgVMID); // ineffecient [[[FIXME]]]
if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) {
--- a/jdk/src/jdk.crypto.pkcs11/share/classes/module-info.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/module-info.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, 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
@@ -26,8 +26,6 @@
module jdk.crypto.pkcs11 {
// Depends on SunEC provider for EC related functionality
requires jdk.crypto.ec;
- // 8153371
- requires jdk.unsupported;
provides java.security.Provider with sun.security.pkcs11.SunPKCS11;
}
--- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/SunPKCS11.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/SunPKCS11.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, 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
@@ -42,7 +42,6 @@
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.TextOutputCallback;
-import sun.misc.ManagedLocalsThread;
import sun.security.util.Debug;
import sun.security.util.ResourcesMgr;
@@ -816,7 +815,7 @@
return;
}
final TokenPoller poller = new TokenPoller(this);
- Thread t = new ManagedLocalsThread(poller, "Poller " + getName());
+ Thread t = new Thread(null, poller, "Poller " + getName(), 0, false);
t.setDaemon(true);
t.setPriority(Thread.MIN_PRIORITY);
t.start();
--- a/jdk/src/jdk.httpserver/share/classes/module-info.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/jdk.httpserver/share/classes/module-info.java Thu Apr 21 13:37:31 2016 -0700
@@ -25,8 +25,7 @@
module jdk.httpserver {
requires java.logging;
- // 8153372
- requires jdk.unsupported;
+
exports com.sun.net.httpserver;
exports com.sun.net.httpserver.spi;
uses com.sun.net.httpserver.spi.HttpServerProvider;
--- a/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java Thu Apr 21 13:37:31 2016 -0700
@@ -36,7 +36,6 @@
import com.sun.net.httpserver.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
-import sun.misc.ManagedLocalsThread;
import sun.net.httpserver.HttpConnection.State;
/**
@@ -143,7 +142,7 @@
if (executor == null) {
executor = new DefaultExecutor();
}
- dispatcherThread = new ManagedLocalsThread(dispatcher);
+ dispatcherThread = new Thread(null, dispatcher, "HTTP-Dispatcher", 0, false);
started = true;
dispatcherThread.start();
}
--- a/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionExecuter.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionExecuter.java Thu Apr 21 13:37:31 2016 -0700
@@ -83,14 +83,14 @@
if (op == null) {
return evaluate(l);
} else {
- Double lval = new Double(((Number)evaluate(l)).doubleValue());
- Double rval = new Double(((Number)evaluate(r)).doubleValue());
- double result = op.eval(lval.doubleValue(), rval.doubleValue());
+ double lval = ((Number)evaluate(l)).doubleValue();
+ double rval = ((Number)evaluate(r)).doubleValue();
+ double result = op.eval(lval, rval);
if (debug) {
System.out.println("Performed Operation: " + lval + op + rval
+ " = " + result);
}
- return new Double(result);
+ return Double.valueOf(result);
}
}
}
--- a/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionResolver.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionResolver.java Thu Apr 21 13:37:31 2016 -0700
@@ -71,7 +71,7 @@
if (m == null) {
System.err.println("Warning: Unresolved Symbol: "
+ id.getName() + " substituted NaN");
- return new Literal(new Double(Double.NaN));
+ return new Literal(Double.valueOf(Double.NaN));
}
if (m.getVariability() == Variability.CONSTANT) {
if (debug) {
@@ -105,7 +105,7 @@
Literal rl = (Literal)r;
boolean warn = false;
- Double nan = new Double(Double.NaN);
+ Double nan = Double.valueOf(Double.NaN);
if (ll.getValue() instanceof String) {
warn = true; ll.setValue(nan);
}
@@ -129,7 +129,7 @@
+ " (right = " + rn.doubleValue() + ")"
+ " to literal value " + result);
}
- return new Literal(new Double(result));
+ return new Literal(Double.valueOf(result));
}
}
--- a/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/Parser.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/Parser.java Thu Apr 21 13:37:31 2016 -0700
@@ -324,7 +324,7 @@
case StreamTokenizer.TT_NUMBER:
double literal = lookahead.nval;
matchNumber();
- e = new Literal(new Double(literal));
+ e = new Literal(Double.valueOf(literal));
log(pdebug, "Parsed: number -> " + literal);
break;
default:
@@ -360,7 +360,7 @@
e1.setOperator(op);
e1.setRight(e);
log(pdebug, "Parsed: unary -> " + e1);
- e1.setLeft(new Literal(new Double(0)));
+ e1.setLeft(new Literal(Double.valueOf(0)));
e = e1;
}
}
--- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Commands.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Commands.java Thu Apr 21 13:37:31 2016 -0700
@@ -478,7 +478,7 @@
ThreadGroupReference tg = it.nextThreadGroup();
++cnt;
MessageOutput.println("thread group number description name",
- new Object [] { new Integer (cnt),
+ new Object [] { Integer.valueOf(cnt),
Env.description(tg),
tg.name()});
}
@@ -1014,7 +1014,7 @@
return MessageOutput.format("locationString",
new Object [] {loc.declaringType().name(),
loc.method().name(),
- new Integer (loc.lineNumber()),
+ Integer.valueOf(loc.lineNumber()),
Long.valueOf(loc.codeIndex())});
}
@@ -1467,7 +1467,7 @@
MessageOutput.println("Line number information not available for");
} else if (Env.sourceLine(loc, lineno) == null) {
MessageOutput.println("is an invalid line number for",
- new Object [] {new Integer (lineno),
+ new Object [] {Integer.valueOf(lineno),
refType.name()});
} else {
for (int i = startLine; i <= endLine; i++) {
@@ -1477,11 +1477,11 @@
}
if (i == lineno) {
MessageOutput.println("source line number current line and line",
- new Object [] {new Integer (i),
+ new Object [] {Integer.valueOf(i),
sourceLine});
} else {
MessageOutput.println("source line number and line",
- new Object [] {new Integer (i),
+ new Object [] {Integer.valueOf(i),
sourceLine});
}
}
@@ -1725,7 +1725,7 @@
} else {
MessageOutput.println("Owned by:",
new Object [] {owner.name(),
- new Integer (object.entryCount())});
+ Integer.valueOf(object.entryCount())});
}
List<ThreadReference> waiters = object.waitingThreads();
if (waiters.size() == 0) {
--- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/MessageOutput.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/MessageOutput.java Thu Apr 21 13:37:31 2016 -0700
@@ -198,7 +198,7 @@
(MessageOutput.format("jdb prompt thread name and current stack frame",
new Object [] {
threadInfo.getThread().name(),
- new Integer (threadInfo.getCurrentFrameIndex() + 1)}));
+ Integer.valueOf(threadInfo.getCurrentFrameIndex() + 1)}));
}
System.out.flush();
}
--- a/jdk/test/ProblemList.txt Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/ProblemList.txt Thu Apr 21 13:37:31 2016 -0700
@@ -335,10 +335,6 @@
com/sun/jdi/GetLocalVariables4Test.sh 8067354 windows-all
-com/sun/jdi/InterfaceMethodsTest.java 8152586 generic-all
-
-com/sun/jdi/InvokeTest.java 8152586 generic-all
-
############################################################################
# jdk_util
--- a/jdk/test/com/sun/jdi/ShellScaffold.sh Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/com/sun/jdi/ShellScaffold.sh Thu Apr 21 13:37:31 2016 -0700
@@ -924,7 +924,7 @@
# If jstack exists, so will jps
# Show stack traces of jdb and debuggee as a possible debugging aid.
jdbCmd=`$jdk/bin/jps -v | $grep $jdbKeyword`
- realJdbPid=`echo "$jdbCmd" | sed -e 's@ TTY.*@@'`
+ realJdbPid=`echo "$jdbCmd" | sed -e 's@ .*@@'`
if [ ! -z "$realJdbPid" ] ; then
echo "-- jdb process info ----------------------" >&2
echo " $jdbCmd" >&2
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/jdi/SunBootClassPathEmptyTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2016, 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 com.sun.jdi.connect.*;
+import com.sun.jdi.*;
+import java.util.Map;
+import java.util.List;
+import jdk.test.lib.Asserts;
+
+/*
+ * @test
+ * @summary Verifies that PathSearchingVirtualMachine.bootClassPath()
+ * returns an empty list in case no bootclass path specified
+ * regardless of sun.boot.class.path option, which is now obsolete
+ * @library /test/lib/share/classes
+ * @compile TestClass.java
+ * @compile SunBootClassPathEmptyTest.java
+ * @run main/othervm SunBootClassPathEmptyTest
+ */
+public class SunBootClassPathEmptyTest {
+
+ /**
+ * Helper class to facilitate the debuggee VM launching
+ */
+ private static class VmConnector {
+
+ LaunchingConnector lc;
+ VirtualMachine vm;
+
+ VmConnector() {
+ for (LaunchingConnector c : Bootstrap.virtualMachineManager().launchingConnectors()) {
+ System.out.println("name: " + c.name());
+ if (c.name().equals("com.sun.jdi.CommandLineLaunch")) {
+ lc = c;
+ break;
+ }
+ }
+ if (lc == null) {
+ throw new RuntimeException("Connector not found");
+ }
+ }
+
+ PathSearchingVirtualMachine launchVm(String cmdLine, String options) throws Exception {
+ Map<String, Connector.Argument> vmArgs = lc.defaultArguments();
+ vmArgs.get("main").setValue(cmdLine);
+ if (options != null) {
+ vmArgs.get("options").setValue(options);
+ }
+ System.out.println("Debugger is launching vm ...");
+ vm = lc.launch(vmArgs);
+ if (!(vm instanceof PathSearchingVirtualMachine)) {
+ throw new RuntimeException("VM is not a PathSearchingVirtualMachine");
+ }
+ return (PathSearchingVirtualMachine) vm;
+ }
+
+ }
+
+ private static VmConnector connector = new VmConnector();
+
+ public static void main(String[] args) throws Exception {
+ testWithObsoleteClassPathOption(null);
+ testWithObsoleteClassPathOption("someclasspath");
+ }
+
+ private static void testWithObsoleteClassPathOption(String obsoleteClassPath) throws Exception {
+ PathSearchingVirtualMachine vm = connector.launchVm("TestClass", makeClassPathOptions(obsoleteClassPath));
+ List<String> bootClassPath = vm.bootClassPath();
+ Asserts.assertNotNull(bootClassPath, "Expected bootClassPath to be empty but was null");
+ Asserts.assertEquals(0, bootClassPath.size(), "Expected bootClassPath.size() 0 but was: " + bootClassPath.size());
+ }
+
+ private static String makeClassPathOptions(String obsoleteClassPath) {
+ return obsoleteClassPath == null ? null : "-Dsun.boot.class.path=" + obsoleteClassPath;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/jdi/TestClass.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+public class TestClass {
+
+ public static void main(String[] args) {
+ System.out.println("This is a test");
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Button/ActionEventTest/ActionEventTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2016, 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 6191390
+ * @summary Verify that ActionEvent is received with correct modifiers set.
+ * @run main/manual ActionEventTest
+ */
+
+import java.awt.AWTException;
+import java.awt.FlowLayout;
+import java.awt.Frame;
+import java.awt.Button;
+import java.awt.TextArea;
+import java.awt.Robot;
+import java.awt.Point;
+import java.awt.event.InputEvent;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+
+public class ActionEventTest extends Frame {
+ Button button;
+ Robot robot;
+ TextArea instructions;
+ public static boolean isProgInterruption = false;
+ static Thread mainThread = null;
+ static int sleepTime = 300000;
+
+ public ActionEventTest() {
+ try {
+ robot = new Robot();
+ } catch(AWTException e) {
+ throw new RuntimeException(e.getMessage());
+ }
+
+ button = new Button("ClickMe");
+ button.setEnabled(true);
+
+ instructions = new TextArea(10, 50);
+ instructions.setText(
+ " This is a manual test\n" +
+ " Keep the Alt, Shift & Ctrl Keys pressed &\n" +
+ " Click 'ClickMe' button with left mouse button\n" +
+ " Test exits automatically after mouse click.");
+
+ add(button);
+ add(instructions);
+ setSize(400,400);
+ setLayout(new FlowLayout());
+ pack();
+ setVisible(true);
+ robot.waitForIdle();
+
+ button.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent ae) {
+ int md = ae.getModifiers();
+ int expectedMask = ActionEvent.ALT_MASK | ActionEvent.CTRL_MASK
+ | ActionEvent.SHIFT_MASK;
+
+ isProgInterruption = true;
+ mainThread.interrupt();
+ if ((md & expectedMask) != expectedMask) {
+ throw new RuntimeException("Action Event modifiers"
+ + " are not set correctly.");
+ }
+ }
+ });
+ }
+
+ public static void main(String args[]) throws Exception {
+ mainThread = Thread.currentThread();
+ ActionEventTest test = new ActionEventTest();
+ try {
+ mainThread.sleep(sleepTime);
+ } catch (InterruptedException e) {
+ if (!isProgInterruption) {
+ throw e;
+ }
+ }
+ test.dispose();
+ if (!isProgInterruption) {
+ throw new RuntimeException("Timed out after " + sleepTime / 1000
+ + " seconds");
+ }
+ }
+}
--- a/jdk/test/java/awt/Component/CompEventOnHiddenComponent/CompEventOnHiddenComponent.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/java/awt/Component/CompEventOnHiddenComponent/CompEventOnHiddenComponent.java Thu Apr 21 13:37:31 2016 -0700
@@ -25,7 +25,7 @@
/*
@test
- @bug 6383903
+ @bug 6383903 8144166
@summary REGRESSION: componentMoved is now getting called for some hidden components
@author andrei.dmitriev: area=awt.component
@run main CompEventOnHiddenComponent
--- a/jdk/test/java/awt/FontClass/CreateFont/CreateFontArrayTest.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/java/awt/FontClass/CreateFont/CreateFontArrayTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -23,9 +23,9 @@
/*
* @test
- * @bug 8055463
+ * @bug 8055463 8153272
* @summary Test createFont APIs
- * @run CreateFontArrayTest
+ * @run main CreateFontArrayTest
*/
import java.awt.Font;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/FontClass/TextRequiresLayoutTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2016, 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 8146324
+ * @summary Test Font.textRequiresLayout
+ */
+
+import java.awt.Font;
+
+public class TextRequiresLayoutTest {
+
+ public static void main(String args[]) {
+
+ String simpleStr = "Hello World";
+ String complexStr = "\u0641\u0642\u0643";
+ char[] simpleChars = simpleStr.toCharArray();
+ char[] complexChars = complexStr.toCharArray();
+
+ if (Font.textRequiresLayout(simpleChars, 0, simpleChars.length)) {
+ throw new RuntimeException("Simple text should not need layout");
+ }
+
+ if (!Font.textRequiresLayout(complexChars, 0, complexChars.length)) {
+ throw new RuntimeException("Complex text should need layout");
+ }
+
+ if (Font.textRequiresLayout(complexChars, 0, 0)) {
+ throw new RuntimeException("Empty text should not need layout");
+ }
+
+ boolean except = false;
+ try {
+ Font.textRequiresLayout(null, 0, 0);
+ } catch (NullPointerException npe) {
+ except = true;
+ }
+ if (!except) {
+ throw new RuntimeException("No expected IllegalArgumentException");
+ }
+
+ except = false;
+ try {
+ Font.textRequiresLayout(complexChars, -1, 0);
+ } catch (ArrayIndexOutOfBoundsException aioobe) {
+ except = true;
+ }
+ if (!except) {
+ throw new
+ RuntimeException("No expected ArrayIndexOutOfBoundsException");
+ }
+
+ except = false;
+ try {
+ Font.textRequiresLayout(complexChars, 0, complexChars.length+1);
+ } catch (ArrayIndexOutOfBoundsException aioobe) {
+ except = true;
+ }
+ if (!except) {
+ throw new
+ RuntimeException("No expected ArrayIndexOutOfBoundsException");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/List/ActionEventTest/ActionEventTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2016, 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 6191390
+ * @summary Verify that ActionEvent is received with correct modifiers set.
+ * @run main ActionEventTest
+ */
+
+import java.awt.AWTException;
+import java.awt.FlowLayout;
+import java.awt.Frame;
+import java.awt.List;
+import java.awt.Robot;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+
+public class ActionEventTest extends Frame {
+ List list;
+ Robot robot;
+
+ public ActionEventTest() {
+ try {
+ robot = new Robot();
+ } catch(AWTException e) {
+ throw new RuntimeException(e.getMessage());
+ }
+
+ list = new List(1, false);
+ list.add("0");
+ add(list);
+ setSize(400,400);
+ setLayout(new FlowLayout());
+ pack();
+ setVisible(true);
+ robot.waitForIdle();
+ }
+
+ void performTest() {
+ list.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent ae) {
+ int md = ae.getModifiers();
+ int expectedMask = ActionEvent.ALT_MASK | ActionEvent.CTRL_MASK
+ | ActionEvent.SHIFT_MASK;
+
+ if ((md & expectedMask) != expectedMask) {
+
+ robot.keyRelease(KeyEvent.VK_ALT);
+ robot.keyRelease(KeyEvent.VK_SHIFT);
+ robot.keyRelease(KeyEvent.VK_CONTROL);
+ dispose();
+ throw new RuntimeException("Action Event modifiers are not"
+ + " set correctly.");
+ }
+ }
+ });
+
+ list.select(0);
+ robot.keyPress(KeyEvent.VK_ALT);
+ robot.keyPress(KeyEvent.VK_SHIFT);
+ robot.keyPress(KeyEvent.VK_CONTROL);
+ // Press Enter on list item, to generate action event.
+ robot.keyPress(KeyEvent.VK_ENTER);
+ robot.keyRelease(KeyEvent.VK_ENTER);
+ robot.waitForIdle();
+ robot.keyRelease(KeyEvent.VK_ALT);
+ robot.keyRelease(KeyEvent.VK_SHIFT);
+ robot.keyRelease(KeyEvent.VK_CONTROL);
+ robot.waitForIdle();
+ }
+
+ public static void main(String args[]) {
+ ActionEventTest test = new ActionEventTest();
+ test.performTest();
+ test.dispose();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/List/ItemEventTest/ItemEventTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2016, 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 8033936
+ * @summary Verify that correct ItemEvent is received while selection &
+ * deselection of multi select List items.
+ */
+
+import java.awt.AWTException;
+import java.awt.Event;
+import java.awt.FlowLayout;
+import java.awt.Frame;
+import java.awt.List;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Robot;
+import java.awt.event.KeyEvent;
+import java.awt.event.InputEvent;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+
+public class ItemEventTest extends Frame
+{
+ List list;
+ final String expectedSelectionOrder;
+ StringBuilder actualSelectionOrder;
+ Robot robot;
+
+ public ItemEventTest()
+ {
+ try {
+ robot = new Robot();
+ } catch(AWTException e) {
+ throw new RuntimeException(e.getMessage());
+ }
+ expectedSelectionOrder = "01230123";
+
+ list = new List(4, true);
+ list.add("0");
+ list.add("1");
+ list.add("2");
+ list.add("3");
+
+ add(list);
+ setSize(400,400);
+ setLayout(new FlowLayout());
+ pack();
+ setVisible(true);
+ robot.waitForIdle();
+ }
+
+ @Override
+ public boolean handleEvent(Event e) {
+ if (e.target instanceof List) {
+ if (e.id == Event.LIST_DESELECT || e.id == Event.LIST_SELECT) {
+ actualSelectionOrder.append(e.arg);
+ }
+ }
+ return true;
+ }
+
+ void testHandleEvent() {
+ // When no ItemListener is added to List, parent's handleEvent is
+ // called with ItemEvent.
+ performTest();
+ }
+
+ void testItemListener() {
+ list.addItemListener(new ItemListener() {
+ @Override
+ public void itemStateChanged(ItemEvent ie) {
+ actualSelectionOrder.append(ie.getItem());
+ }
+ });
+ performTest();
+ }
+
+ void performTest() {
+ actualSelectionOrder = new StringBuilder();
+ Point loc = list.getLocationOnScreen();
+ Rectangle rect = list.getBounds();
+ int dY = rect.height / list.getItemCount();
+ loc = new Point(loc.x + 10, loc.y + 5);
+
+ String osName = System.getProperty("os.name");
+ boolean isMac = osName.contains("Mac") || osName.contains("mac");
+ if(isMac) {
+ robot.keyPress(KeyEvent.VK_META);
+ }
+
+ // First loop to select & Second loop to deselect the list items.
+ for (int j = 0; j < 2; ++j) {
+ for (int i = 0; i < list.getItemCount(); ++i) {
+ robot.mouseMove(loc.x, loc.y + i * dY);
+ robot.mousePress(InputEvent.BUTTON1_MASK);
+ robot.delay(100);
+ robot.mouseRelease(InputEvent.BUTTON1_MASK);
+ robot.waitForIdle();
+ }
+ }
+
+ if(isMac) {
+ robot.keyRelease(KeyEvent.VK_META);
+ }
+
+ if (!expectedSelectionOrder.equals(actualSelectionOrder.toString())) {
+ dispose();
+ throw new RuntimeException("ItemEvent for selection & deselection"
+ + " of multi select List's item is not correct"
+ + " Expected : " + expectedSelectionOrder
+ + " Actual : " + actualSelectionOrder);
+ }
+ }
+
+ public static void main(String args[]) {
+ ItemEventTest test = new ItemEventTest();
+ test.testHandleEvent();
+ test.testItemListener();
+ test.dispose();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/MenuBar/ActionEventTest/ActionEventTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2016, 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 6191390
+ * @summary Verify that ActionEvent is received with correct modifiers set.
+ * @run main/manual ActionEventTest
+ */
+
+import java.awt.Frame;
+import java.awt.Menu;
+import java.awt.MenuBar;
+import java.awt.MenuItem;
+import java.awt.TextArea;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+public final class ActionEventTest extends Frame {
+
+ MenuBar menuBar;
+ TextArea instructions;
+ public static boolean isProgInterruption = false;
+ static Thread mainThread = null;
+ static int sleepTime = 300000;
+
+ public ActionEventTest() {
+ menuBar = new MenuBar();
+ Menu menu = new Menu("Menu1");
+ MenuItem menuItem = new MenuItem("MenuItem");
+
+ menuItem.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent ae) {
+ System.out.println("actionPerformed");
+ int md = ae.getModifiers();
+ int expectedMask = ActionEvent.ALT_MASK | ActionEvent.CTRL_MASK
+ | ActionEvent.SHIFT_MASK;
+
+ isProgInterruption = true;
+ mainThread.interrupt();
+ if ((md & expectedMask) != expectedMask) {
+ throw new RuntimeException("Action Event modifiers are not"
+ + " set correctly.");
+ }
+ }
+ });
+ menu.add(menuItem);
+ menuBar.add(menu);
+ setMenuBar(menuBar);
+
+ instructions = new TextArea(10, 50);
+ instructions.setText(
+ " This is a manual test\n" +
+ " Keep the Alt, Shift & Ctrl Keys pressed while doing next steps\n" +
+ " Click 'Menu1' Menu from the Menu Bar\n" +
+ " It will show 'MenuItem'\n" +
+ " Left mouse Click the 'MenuItem'\n" +
+ " Test exits automatically after mouse click.");
+ add(instructions);
+
+ setSize(400, 400);
+ setVisible(true);
+ validate();
+ }
+
+
+ public static void main(final String[] args) throws Exception {
+ mainThread = Thread.currentThread();
+ ActionEventTest test = new ActionEventTest();
+ try {
+ mainThread.sleep(sleepTime);
+ } catch (InterruptedException e) {
+ if (!isProgInterruption) {
+ throw e;
+ }
+ }
+ test.dispose();
+ if (!isProgInterruption) {
+ throw new RuntimeException("Timed out after " + sleepTime / 1000
+ + " seconds");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/PrintJob/JobAttrUpdateTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2016, 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 6357905
+ * @summary JobAttributes.getFromPage() and getToPage() always returns 1
+ * @run main/manual JobAttrUpdateTest
+ */
+import java.awt.BorderLayout;
+import java.awt.FlowLayout;
+import java.awt.JobAttributes;
+import java.awt.PrintJob;
+import java.awt.Toolkit;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+import javax.swing.SwingUtilities;
+
+public class JobAttrUpdateTest {
+
+ private static Thread mainThread;
+ private static boolean testPassed;
+ private static boolean testGeneratedInterrupt;
+
+ public static void main(String[] args) throws Exception {
+ SwingUtilities.invokeAndWait(() -> {
+ doTest(JobAttrUpdateTest::printTest);
+ });
+ mainThread = Thread.currentThread();
+ try {
+ Thread.sleep(30000);
+ } catch (InterruptedException e) {
+ if (!testPassed && testGeneratedInterrupt) {
+ throw new RuntimeException(""
+ + "JobAttributes.getFromPage(),getToPage() not updated correctly");
+ }
+ }
+ if (!testGeneratedInterrupt) {
+ throw new RuntimeException("user has not executed the test");
+ }
+ }
+
+ private static void printTest() {
+ JobAttributes ja = new JobAttributes();
+
+ Toolkit tk = Toolkit.getDefaultToolkit();
+ // ja.setToPage(4);
+ // ja.setFromPage(3);
+ // show dialog
+ PrintJob pjob = tk.getPrintJob(new JFrame(), "test", ja, null);
+ if (pjob == null) {
+ return;
+ }
+
+
+ if (ja.getDefaultSelection() == JobAttributes.DefaultSelectionType.RANGE) {
+ int fromPage = ja.getFromPage();
+ int toPage = ja.getToPage();
+ if (fromPage != 2 || toPage != 3) {
+ fail();
+ } else {
+ pass();
+ }
+ }
+ }
+
+ public static synchronized void pass() {
+ testPassed = true;
+ testGeneratedInterrupt = true;
+ mainThread.interrupt();
+ }
+
+ public static synchronized void fail() {
+ testPassed = false;
+ testGeneratedInterrupt = true;
+ mainThread.interrupt();
+ }
+
+ private static void doTest(Runnable action) {
+ String description
+ = " A print dialog will be shown.\n "
+ + " Please select Pages within Page-range.\n"
+ + " and enter From 2 and To 3. Then Select OK.";
+
+ final JDialog dialog = new JDialog();
+ dialog.setTitle("JobAttribute Updation Test");
+ JTextArea textArea = new JTextArea(description);
+ textArea.setEditable(false);
+ final JButton testButton = new JButton("Start Test");
+
+ testButton.addActionListener((e) -> {
+ testButton.setEnabled(false);
+ action.run();
+ });
+ JPanel mainPanel = new JPanel(new BorderLayout());
+ mainPanel.add(textArea, BorderLayout.CENTER);
+ JPanel buttonPanel = new JPanel(new FlowLayout());
+ buttonPanel.add(testButton);
+ mainPanel.add(buttonPanel, BorderLayout.SOUTH);
+ dialog.add(mainPanel);
+ dialog.pack();
+ dialog.setVisible(true);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/TrayIcon/ActionEventTest/ActionEventTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2016, 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 6191390
+ * @summary Verify that ActionEvent is received with correct modifiers set.
+ * @library ../../../../lib/testlibrary ../
+ * @build ExtendedRobot SystemTrayIconHelper
+ */
+
+import java.awt.Image;
+import java.awt.TrayIcon;
+import java.awt.SystemTray;
+import java.awt.Robot;
+import java.awt.EventQueue;
+import java.awt.Point;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.awt.image.BufferedImage;
+
+public class ActionEventTest {
+
+ Image image;
+ TrayIcon icon;
+ Robot robot;
+
+ public static void main(String[] args) throws Exception {
+ if (!SystemTray.isSupported()) {
+ System.out.println("SystemTray not supported on the platform." +
+ " Marking the test passed.");
+ } else {
+ if (System.getProperty("os.name").toLowerCase().startsWith("win")) {
+ System.err.println(
+ "Test can fail on Windows platform\n"+
+ "On Windows 7, by default icon hides behind icon pool\n" +
+ "Due to which test might fail\n" +
+ "Set \"Right mouse click\" -> " +
+ "\"Customize notification icons\" -> \"Always show " +
+ "all icons and notifications on the taskbar\" true " +
+ "to avoid this problem.\nOR change behavior only for " +
+ "Java SE tray icon and rerun test.");
+ }
+
+ ActionEventTest test = new ActionEventTest();
+ test.doTest();
+ test.clear();
+ }
+ }
+
+ public ActionEventTest() throws Exception {
+ robot = new Robot();
+ EventQueue.invokeAndWait(this::initializeGUI);
+ }
+
+ private void initializeGUI() {
+
+ icon = new TrayIcon(
+ new BufferedImage(20, 20, BufferedImage.TYPE_INT_RGB), "ti");
+ icon.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent ae) {
+ int md = ae.getModifiers();
+ int expectedMask = ActionEvent.ALT_MASK | ActionEvent.CTRL_MASK
+ | ActionEvent.SHIFT_MASK;
+
+ if ((md & expectedMask) != expectedMask) {
+ clear();
+ throw new RuntimeException("Action Event modifiers are not"
+ + " set correctly.");
+ }
+ }
+ });
+
+ try {
+ SystemTray.getSystemTray().add(icon);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void clear() {
+ SystemTray.getSystemTray().remove(icon);
+ }
+
+ void doTest() throws Exception {
+ robot.keyPress(KeyEvent.VK_ALT);
+ robot.keyPress(KeyEvent.VK_SHIFT);
+ robot.keyPress(KeyEvent.VK_CONTROL);
+
+ Point iconPosition = SystemTrayIconHelper.getTrayIconLocation(icon);
+ if (iconPosition == null) {
+ throw new RuntimeException("Unable to find the icon location!");
+ }
+
+ robot.mouseMove(iconPosition.x, iconPosition.y);
+ robot.waitForIdle();
+
+ robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
+ robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
+ robot.delay(100);
+ robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
+ robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
+ robot.delay(100);
+ robot.waitForIdle();
+ robot.keyRelease(KeyEvent.VK_ALT);
+ robot.keyRelease(KeyEvent.VK_SHIFT);
+ robot.keyRelease(KeyEvent.VK_CONTROL);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/font/MonospacedGlyphWidth/MonospacedGlyphWidthTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2016, 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 8073400
+ * @summary Some Monospaced logical fonts have a different width
+ * @author Dmitry Markov
+ * @run main MonospacedGlyphWidthTest
+ */
+import java.awt.*;
+import java.awt.font.FontRenderContext;
+
+public class MonospacedGlyphWidthTest {
+ private static final int START_INDEX = 0x2018;
+ private static final int END_INDEX = 0x201F;
+
+ public static void main(String[] args) {
+ Font font = new Font(Font.MONOSPACED, Font.PLAIN, 12);
+ double width = getCharWidth(font, 'a');
+
+ for (int i = START_INDEX; i <= END_INDEX; i++) {
+ if (width != getCharWidth(font, (char)i)) {
+ throw new RuntimeException("Test Failed: characters have different width!");
+ }
+ }
+ System.out.println("Test Passed!");
+ }
+
+ private static double getCharWidth(Font font, char c) {
+ FontRenderContext fontRenderContext = new FontRenderContext(null, false, false);
+ return font.getStringBounds(new char[] {c}, 0, 1, fontRenderContext).getWidth();
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/image/RasterCreationTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 2016, 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.awt.Point;
+import java.awt.image.DataBuffer;
+import java.awt.image.DataBufferByte;
+import java.awt.image.DataBufferDouble;
+import java.awt.image.DataBufferFloat;
+import java.awt.image.DataBufferInt;
+import java.awt.image.DataBufferShort;
+import java.awt.image.DataBufferUShort;
+import java.awt.image.Raster;
+import java.awt.image.SampleModel;
+import java.awt.image.MultiPixelPackedSampleModel;
+import java.awt.image.PixelInterleavedSampleModel;
+import java.awt.image.SinglePixelPackedSampleModel;
+
+/*
+ * @test
+ * @bug 6353518
+ * @summary Test possible combinations of Raster creation
+ * Test fails if any of Raster.createXXX() method throws exception.
+ */
+public class RasterCreationTest {
+
+ public static void main(String[] args) {
+
+ final int width = 10;
+ final int height = 5;
+ final int imageSize = width * height;
+ Point location = new Point(0, 0);
+ int[] bandOffsets = {0};
+ int[] bitMask = {0x00ff0000, 0x0000ff00, 0xff, 0x0};
+
+ SampleModel[] inputSampleModels = {
+ new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE,
+ 1, 1, 1, 1, bandOffsets),
+ new PixelInterleavedSampleModel(DataBuffer.TYPE_USHORT,
+ 1, 1, 1, 1, bandOffsets),
+ new PixelInterleavedSampleModel(DataBuffer.TYPE_INT,
+ 1, 1, 1, 1, bandOffsets),
+ new SinglePixelPackedSampleModel(DataBuffer.TYPE_BYTE,
+ width, height, bitMask),
+ new SinglePixelPackedSampleModel(DataBuffer.TYPE_USHORT,
+ width, height, bitMask),
+ new SinglePixelPackedSampleModel(DataBuffer.TYPE_INT,
+ width, height, bitMask),
+ new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE,
+ width, height, 4),
+ new MultiPixelPackedSampleModel(DataBuffer.TYPE_USHORT,
+ width, height, 2),
+ new MultiPixelPackedSampleModel(DataBuffer.TYPE_INT,
+ width, height, 2)
+ };
+
+ // ---------------------------------------------------------------------
+ // Test ability to create Raster & WritableRaster with DataBuffer
+ // classes
+ // ---------------------------------------------------------------------
+ DataBuffer[] inputDataBuffer = {
+ new DataBufferByte(imageSize),
+ new DataBufferUShort(imageSize),
+ new DataBufferInt(imageSize, 1),
+ new DataBufferShort(imageSize),
+ new DataBufferFloat(imageSize),
+ new DataBufferDouble(imageSize)
+ };
+
+ for (SampleModel sm : inputSampleModels) {
+ for (DataBuffer db : inputDataBuffer) {
+ // Test Raster creation
+ Raster.createRaster(sm, db, location);
+
+ // Test writableRaster creation
+ Raster.createWritableRaster(sm, db, location);
+ Raster.createWritableRaster(sm, location);
+ }
+ }
+
+ // ---------------------------------------------------------------------
+ // Test ability to create Raster & WritableRaster with custom DataBuffer
+ // classes
+ // ---------------------------------------------------------------------
+ DataBuffer[] myDataBuffer = {
+ new MyDataBufferByte(imageSize),
+ new MyDataBufferUShort(imageSize),
+ new MyDataBufferInt(imageSize),
+ new MyDataBufferShort(imageSize),
+ new MyDataBufferDouble(imageSize),
+ new MyDataBufferFloat(imageSize)
+ };
+
+ for (SampleModel sm : inputSampleModels) {
+ for (DataBuffer db : myDataBuffer) {
+ // Test Raster creation
+ Raster.createRaster(sm, db, location);
+
+ // Test writableRaster creation
+ Raster.createWritableRaster(sm, db, location);
+ Raster.createWritableRaster(sm, location);
+ }
+ }
+
+ // ---------------------------------------------------------------------
+ // Test ability to create InterleavedRaster
+ // ---------------------------------------------------------------------
+ int[] interleavedInputDataTypes = {
+ DataBuffer.TYPE_BYTE,
+ DataBuffer.TYPE_USHORT
+ };
+
+ int numBands = 1;
+
+ for (int i : interleavedInputDataTypes) {
+ Raster.createInterleavedRaster(i, width, height, 1, location);
+ Raster.createInterleavedRaster(i, width, height, width * numBands,
+ numBands, bandOffsets, location);
+ }
+
+ for (int i = 0; i < interleavedInputDataTypes.length ; i++) {
+ DataBuffer d1 = inputDataBuffer[i];
+ DataBuffer d2 = myDataBuffer[i];
+
+ Raster.createInterleavedRaster(d1, width, height, width * numBands,
+ numBands, bandOffsets, location);
+ Raster.createInterleavedRaster(d2, width, height, width * numBands,
+ numBands, bandOffsets, location);
+ }
+
+ // ---------------------------------------------------------------------
+ // Test ability to create BandedRaster
+ // ---------------------------------------------------------------------
+ int[] bankIndices = new int[numBands];
+ bankIndices[0] = 0;
+
+ int[] bandedInputDataTypes = {
+ DataBuffer.TYPE_BYTE,
+ DataBuffer.TYPE_USHORT,
+ DataBuffer.TYPE_INT
+ };
+
+ for (int i : bandedInputDataTypes) {
+ Raster.createBandedRaster(i, width, height, 1, location);
+ Raster.createBandedRaster(i, width, height, width,
+ bankIndices, bandOffsets, location);
+ }
+
+ for (int i = 0; i < bandedInputDataTypes.length; i++) {
+ DataBuffer d1 = inputDataBuffer[i];
+ DataBuffer d2 = myDataBuffer[i];
+
+ Raster.createBandedRaster(d1, width, height, width,
+ bankIndices, bandOffsets, location);
+ Raster.createBandedRaster(d2, width, height, width,
+ bankIndices, bandOffsets, location);
+ }
+
+ // ---------------------------------------------------------------------
+ // Test ability to create PackedRaster
+ // ---------------------------------------------------------------------
+ int[] bandMasks = new int[numBands];
+ bandMasks[0] = 0;
+
+ int packedInputDataTypes[] = {
+ DataBuffer.TYPE_BYTE,
+ DataBuffer.TYPE_USHORT,
+ DataBuffer.TYPE_INT
+ };
+
+ for (int i : packedInputDataTypes) {
+ Raster.createPackedRaster(i, width, height, bandMasks, location);
+
+ for (int bits = 1; bits < 5; bits *= 2) {
+ Raster.createPackedRaster(i, width, height, 1, bits, location);
+ }
+ }
+
+ for (int i = 0; i < packedInputDataTypes.length; i++) {
+ DataBuffer d1 = inputDataBuffer[i];
+ DataBuffer d2 = myDataBuffer[i];
+
+ for (int bits = 1; bits < 5; bits *= 2) {
+ Raster.createPackedRaster(d1, width, height, bits, location);
+ Raster.createPackedRaster(d2, width, height, bits, location);
+ }
+
+ Raster.createPackedRaster(d1, width, height, 1,bandMasks, location);
+ Raster.createPackedRaster(d2, width, height, 1,bandMasks, location);
+ }
+ }
+}
+
+// ---------------------------------------------------------------------
+// Custom DataBuffer classes for testing purpose
+// ---------------------------------------------------------------------
+final class MyDataBufferByte extends DataBuffer {
+
+ byte[] data;
+ byte[][] bankdata;
+
+ public MyDataBufferByte(int size) {
+ super(TYPE_BYTE, size);
+ data = new byte[size];
+ bankdata = new byte[1][];
+ bankdata[0] = data;
+ }
+
+ @Override
+ public int getElem(int bank, int i) {
+ return bankdata[bank][i + offsets[bank]];
+ }
+
+ @Override
+ public void setElem(int bank, int i, int val) {
+ bankdata[bank][i + offsets[bank]] = (byte) val;
+ }
+}
+
+final class MyDataBufferDouble extends DataBuffer {
+
+ double[] data;
+ double[][] bankdata;
+
+ public MyDataBufferDouble(int size) {
+ super(TYPE_DOUBLE, size);
+ data = new double[size];
+ bankdata = new double[1][];
+ bankdata[0] = data;
+ }
+
+ @Override
+ public int getElem(int bank, int i) {
+ return (int) bankdata[bank][i + offsets[bank]];
+ }
+
+ @Override
+ public void setElem(int bank, int i, int val) {
+ bankdata[bank][i + offsets[bank]] = (double) val;
+ }
+}
+
+final class MyDataBufferFloat extends DataBuffer {
+
+ float[] data;
+ float[][] bankdata;
+
+ public MyDataBufferFloat(int size) {
+ super(TYPE_FLOAT, size);
+ data = new float[size];
+ bankdata = new float[1][];
+ bankdata[0] = data;
+ }
+
+ @Override
+ public int getElem(int bank, int i) {
+ return (int) bankdata[bank][i + offsets[bank]];
+ }
+
+ @Override
+ public void setElem(int bank, int i, int val) {
+ bankdata[bank][i + offsets[bank]] = (float) val;
+ }
+}
+
+final class MyDataBufferShort extends DataBuffer {
+
+ short[] data;
+ short[][] bankdata;
+
+ public MyDataBufferShort(int size) {
+ super(TYPE_SHORT, size);
+ data = new short[size];
+ bankdata = new short[1][];
+ bankdata[0] = data;
+ }
+
+ @Override
+ public int getElem(int bank, int i) {
+ return bankdata[bank][i + offsets[bank]];
+ }
+
+ @Override
+ public void setElem(int bank, int i, int val) {
+ bankdata[bank][i + offsets[bank]] = (short) val;
+ }
+}
+
+final class MyDataBufferUShort extends DataBuffer {
+
+ short[] data;
+ short[][] bankdata;
+
+ public MyDataBufferUShort(int size) {
+ super(TYPE_USHORT, size);
+ data = new short[size];
+ bankdata = new short[1][];
+ bankdata[0] = data;
+ }
+
+ @Override
+ public int getElem(int bank, int i) {
+ return bankdata[bank][i + offsets[bank]];
+ }
+
+ @Override
+ public void setElem(int bank, int i, int val) {
+ bankdata[bank][i + offsets[bank]] = (short) val;
+ }
+}
+
+final class MyDataBufferInt extends DataBuffer {
+
+ int[] data;
+ int[][] bankdata;
+
+ public MyDataBufferInt(int size) {
+ super(TYPE_INT, size);
+ data = new int[size];
+ bankdata = new int[1][];
+ bankdata[0] = data;
+ }
+
+ @Override
+ public int getElem(int bank, int i) {
+ return bankdata[bank][i + offsets[bank]];
+ }
+
+ @Override
+ public void setElem(int bank, int i, int val) {
+ bankdata[bank][i + offsets[bank]] = (int) val;
+ }
+}
--- a/jdk/test/java/awt/image/multiresolution/MultiResolutionTrayIconTest/MultiResolutionTrayIconTest.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/java/awt/image/multiresolution/MultiResolutionTrayIconTest/MultiResolutionTrayIconTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -24,8 +24,7 @@
/*
@test
- @bug 8150176
- @ignore 8150176
+ @bug 8150176 8151773
@summary Check if correct resolution variant is used for tray icon.
@author a.stepanov
@run applet/manual=yesno MultiResolutionTrayIconTest.html
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/print/PrinterJob/DlgAttrsBug.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2016, 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 8061258
+ * @summary PrinterJob's native Print Dialog does not reflect
+ * specified Copies or Page Ranges
+ * @run main/manual DlgAttrsBug
+ */
+import java.awt.BorderLayout;
+import java.awt.FlowLayout;
+import java.awt.Graphics;
+import java.awt.print.PageFormat;
+import java.awt.print.Printable;
+import java.awt.print.PrinterException;
+import java.awt.print.PrinterJob;
+import javax.print.attribute.HashPrintRequestAttributeSet;
+import javax.print.attribute.PrintRequestAttributeSet;
+import javax.print.attribute.standard.Copies;
+import javax.print.attribute.standard.PageRanges;
+import javax.print.attribute.standard.DialogTypeSelection;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+import javax.swing.SwingUtilities;
+
+
+public class DlgAttrsBug implements Printable {
+ private static Thread mainThread;
+ private static boolean testPassed;
+ private static boolean testGeneratedInterrupt;
+
+ public static void main(String[] args) throws Exception {
+ SwingUtilities.invokeAndWait(() -> {
+ doTest(DlgAttrsBug::printTest);
+ });
+ mainThread = Thread.currentThread();
+ try {
+ Thread.sleep(30000);
+ } catch (InterruptedException e) {
+ if (!testPassed && testGeneratedInterrupt) {
+ throw new RuntimeException("Print Dialog does not " +
+ "reflect Copies or Page Ranges");
+ }
+ }
+ if (!testGeneratedInterrupt) {
+ throw new RuntimeException("user has not executed the test");
+ }
+ }
+
+ private static void printTest() {
+ PrinterJob job = PrinterJob.getPrinterJob();
+ if (job.getPrintService() == null) {
+ System.out.println("No printers. Test cannot continue");
+ return;
+ }
+ job.setPrintable(new DlgAttrsBug());
+ PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
+ aset.add(new Copies(5));
+ aset.add(new PageRanges(3,4));
+ aset.add(DialogTypeSelection.NATIVE);
+ job.printDialog(aset);
+ }
+
+ public static synchronized void pass() {
+ testPassed = true;
+ testGeneratedInterrupt = true;
+ mainThread.interrupt();
+ }
+
+ public static synchronized void fail() {
+ testPassed = false;
+ testGeneratedInterrupt = true;
+ mainThread.interrupt();
+ }
+
+ private static void doTest(Runnable action) {
+ String description
+ = " Visual inspection of print dialog is required.\n"
+ + " A print dialog will be shown.\n "
+ + " Please verify Copies 5 is selected.\n"
+ + " Also verify, Page Range is selected with "
+ + " from page 3 and to Page 4.\n"
+ + " If ok, press PASS else press FAIL";
+
+ final JDialog dialog = new JDialog();
+ dialog.setTitle("printSelectionTest");
+ JTextArea textArea = new JTextArea(description);
+ textArea.setEditable(false);
+ final JButton testButton = new JButton("Start Test");
+ final JButton passButton = new JButton("PASS");
+ passButton.setEnabled(false);
+ passButton.addActionListener((e) -> {
+ dialog.dispose();
+ pass();
+ });
+ final JButton failButton = new JButton("FAIL");
+ failButton.setEnabled(false);
+ failButton.addActionListener((e) -> {
+ dialog.dispose();
+ fail();
+ });
+ testButton.addActionListener((e) -> {
+ testButton.setEnabled(false);
+ action.run();
+ passButton.setEnabled(true);
+ failButton.setEnabled(true);
+ });
+ JPanel mainPanel = new JPanel(new BorderLayout());
+ mainPanel.add(textArea, BorderLayout.CENTER);
+ JPanel buttonPanel = new JPanel(new FlowLayout());
+ buttonPanel.add(testButton);
+ buttonPanel.add(passButton);
+ buttonPanel.add(failButton);
+ mainPanel.add(buttonPanel, BorderLayout.SOUTH);
+ dialog.add(mainPanel);
+ dialog.pack();
+ dialog.setVisible(true);
+ }
+
+ public int print(Graphics g, PageFormat pf, int pi)
+ throws PrinterException {
+ System.out.println("pi = " + pi);
+ if (pi >= 5) {
+ return NO_SUCH_PAGE;
+ }
+ g.drawString("Page : " + (pi+1), 200, 200);
+ return PAGE_EXISTS;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/print/PrinterJob/PrintAttributeUpdateTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2016, 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 8042713
+ @summary Print Dialog does not update attribute set with page range
+ @run main/manual PrintAttributeUpdateTest
+ */
+import java.awt.Component;
+import java.awt.Graphics;
+import java.awt.print.PageFormat;
+import java.awt.print.Pageable;
+import java.awt.print.Printable;
+import java.awt.print.PrinterJob;
+import javax.print.attribute.Attribute;
+import javax.print.attribute.HashPrintRequestAttributeSet;
+import javax.print.attribute.standard.DialogTypeSelection;
+import javax.print.attribute.standard.PageRanges;
+import javax.swing.JOptionPane;
+import javax.swing.SwingUtilities;
+
+public class PrintAttributeUpdateTest implements Pageable, Printable {
+
+ public static void main(String args[]) throws Exception {
+ String[] instructions
+ = {
+ "Select Pages Range From instead of All in print dialog. ",
+ "Then select Print"
+ };
+ SwingUtilities.invokeAndWait(() -> {
+ JOptionPane.showMessageDialog((Component) null,
+ instructions, "Instructions",
+ JOptionPane.INFORMATION_MESSAGE);
+ });
+ HashPrintRequestAttributeSet as = new HashPrintRequestAttributeSet();
+ PrinterJob j = PrinterJob.getPrinterJob();
+ j.setPageable(new PrintAttributeUpdateTest());
+ as.add(DialogTypeSelection.NATIVE);
+ j.printDialog(as);
+ if (as.containsKey(PageRanges.class) == false) {
+ throw new RuntimeException("Print Dialog did not update "
+ + " attribute set with page range");
+ }
+ Attribute attrs[] = as.toArray();
+ for (int i = 0; i < attrs.length; i++) {
+ System.out.println("attr " + attrs[i]);
+ }
+ j.print(as);
+ }
+
+ public int getNumberOfPages() {
+ return UNKNOWN_NUMBER_OF_PAGES;
+ }
+
+ public PageFormat getPageFormat(int pageIndex) {
+ PageFormat pf = new PageFormat();
+ return pf;
+ }
+
+ public Printable getPrintable(int pageIndex) {
+ return this;
+ }
+
+ public int print(Graphics g, PageFormat pgFmt, int pi) {
+ g.drawString("Page : " + (pi + 1), 200, 200);
+
+ return PAGE_EXISTS;
+ }
+
+}
--- a/jdk/test/java/awt/xembed/server/TestXEmbedServerJava.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/java/awt/xembed/server/TestXEmbedServerJava.java Thu Apr 21 13:37:31 2016 -0700
@@ -76,7 +76,23 @@
public Process startClient(Rectangle[] bounds, long window) {
try {
String java_home = System.getProperty("java.home");
- return Runtime.getRuntime().exec(java_home + "/bin/java -XaddExports:java.desktop/sun.awt.X11=ALL-UNNAMED JavaClient " + window);
+ boolean hasModules = true;
+ try {
+ Class.class.getMethod("getModule");
+ }catch(Exception hasModulesEx) {
+ hasModules = false;
+ }
+ if (hasModules) {
+ System.out.println(java_home +
+ "/bin/java -XaddExports:java.desktop/sun.awt.X11=ALL-UNNAMED "+
+ "-XaddExports:java.desktop/sun.awt=ALL-UNNAMED JavaClient " + window);
+ return Runtime.getRuntime().exec(java_home +
+ "/bin/java -XaddExports:java.desktop/sun.awt.X11=ALL-UNNAMED "+
+ "-XaddExports:java.desktop/sun.awt=ALL-UNNAMED JavaClient " + window);
+ }else{
+ System.out.println(java_home + "/bin/java JavaClient " + window);
+ return Runtime.getRuntime().exec(java_home + "/bin/java JavaClient " + window);
+ }
} catch (IOException ex1) {
ex1.printStackTrace();
}
--- a/jdk/test/java/lang/Class/GetPackageTest.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/java/lang/Class/GetPackageTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/**
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -52,7 +52,7 @@
assertEquals(fooClass.getClassLoader(), loader);
}
- @DataProvider(name = "testclasses")
+ @DataProvider(name = "testClasses")
public Object[][] testClasses() {
return new Object[][] {
// primitive type, void, array types
--- a/jdk/test/java/lang/StackWalker/DumpStackTest.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/java/lang/StackWalker/DumpStackTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -28,9 +28,6 @@
* This test should also been run against jdk9 successfully except of
* VM option MemberNameInStackFrame.
* @run main/othervm DumpStackTest
- * @run main/othervm -Dstackwalk.newThrowable=false DumpStackTest
- * @run main/othervm -Dstackwalk.newThrowable=true -XX:-MemberNameInStackFrame DumpStackTest
- * @run main/othervm -Dstackwalk.newThrowable=true -XX:+MemberNameInStackFrame DumpStackTest
*/
import java.lang.invoke.MethodHandle;
--- a/jdk/test/java/lang/StackWalker/GetCallerClassTest.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/java/lang/StackWalker/GetCallerClassTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -25,8 +25,7 @@
* @test
* @bug 8140450
* @summary Basic test for StackWalker.getCallerClass()
- * @run main/othervm -XX:-MemberNameInStackFrame GetCallerClassTest
- * @run main/othervm -XX:+MemberNameInStackFrame GetCallerClassTest
+ * @run main/othervm GetCallerClassTest
* @run main/othervm GetCallerClassTest sm
*/
--- a/jdk/test/java/lang/StackWalker/StackWalkTest.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/java/lang/StackWalker/StackWalkTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -44,10 +44,6 @@
* @run main/othervm/java.security.policy=stackwalktest.policy StackWalkTest
* @run main/othervm StackWalkTest -random:50
* @run main/othervm/java.security.policy=stackwalktest.policy StackWalkTest -random:50
- * @run main/othervm -XX:-MemberNameInStackFrame -Dstackwalk.newThrowable=false StackWalkTest -random:50
- * @run main/othervm -XX:-MemberNameInStackFrame -Dstackwalk.newThrowable=true StackWalkTest -random:50
- * @run main/othervm -XX:+MemberNameInStackFrame -Dstackwalk.newThrowable=false StackWalkTest -random:50
- * @run main/othervm -XX:+MemberNameInStackFrame -Dstackwalk.newThrowable=true StackWalkTest -random:50
* @author danielfuchs, bchristi
* @key randomness
*/
--- a/jdk/test/java/lang/StackWalker/VerifyStackTrace.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/java/lang/StackWalker/VerifyStackTrace.java Thu Apr 21 13:37:31 2016 -0700
@@ -40,8 +40,7 @@
* @summary Verify stack trace information obtained with respect to StackWalker
* options, when the stack contains lambdas, method handle invoke
* virtual calls, and reflection.
- * @run main/othervm -XX:-MemberNameInStackFrame VerifyStackTrace
- * @run main/othervm -XX:+MemberNameInStackFrame VerifyStackTrace
+ * @run main/othervm VerifyStackTrace
* @run main/othervm/java.security.policy=stackwalk.policy VerifyStackTrace
* @author danielfuchs
*/
--- a/jdk/test/java/lang/invoke/LoopCombinatorTest.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/java/lang/invoke/LoopCombinatorTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -26,6 +26,7 @@
/* @test
* @bug 8139885
* @bug 8150635
+ * @bug 8150956
* @bug 8150957
* @bug 8153637
* @run testng/othervm -ea -esa test.java.lang.invoke.LoopCombinatorTest
@@ -266,6 +267,28 @@
}
@Test
+ public static void testWhileVoidInit() throws Throwable {
+ While w = new While();
+ int v = 5;
+ MethodHandle loop = MethodHandles.whileLoop(While.MH_voidInit.bindTo(w), While.MH_voidPred.bindTo(w),
+ While.MH_voidBody.bindTo(w));
+ assertEquals(While.MT_void, loop.type());
+ loop.invoke(v);
+ assertEquals(v, w.i);
+ }
+
+ @Test
+ public static void testDoWhileVoidInit() throws Throwable {
+ While w = new While();
+ int v = 5;
+ MethodHandle loop = MethodHandles.doWhileLoop(While.MH_voidInit.bindTo(w), While.MH_voidBody.bindTo(w),
+ While.MH_voidPred.bindTo(w));
+ assertEquals(While.MT_void, loop.type());
+ loop.invoke(v);
+ assertEquals(v, w.i);
+ }
+
+ @Test
public static void testCountedLoop() throws Throwable {
// String s = "Lambdaman!"; for (int i = 0; i < 13; ++i) { s = "na " + s; } return s; => a variation on a well known theme
MethodHandle fit13 = MethodHandles.constant(int.class, 13);
@@ -275,6 +298,14 @@
}
@Test
+ public static void testCountedLoopVoidInit() throws Throwable {
+ MethodHandle fit5 = MethodHandles.constant(int.class, 5);
+ MethodHandle loop = MethodHandles.countedLoop(fit5, MethodHandles.zero(void.class), Counted.MH_printHello);
+ assertEquals(Counted.MT_countedPrinting, loop.type());
+ loop.invoke();
+ }
+
+ @Test
public static void testCountedArrayLoop() throws Throwable {
// int[] a = new int[]{0}; for (int i = 0; i < 13; ++i) { ++a[0]; } => a[0] == 13
MethodHandle fit13 = MethodHandles.dropArguments(MethodHandles.constant(int.class, 13), 0, int[].class);
@@ -360,7 +391,8 @@
public static void testIterateNullBody() {
boolean caught = false;
try {
- MethodHandles.iteratedLoop(MethodHandles.identity(int.class), MethodHandles.identity(int.class), null);
+ MethodHandles.iteratedLoop(MethodHandles.empty(methodType(Iterator.class, int.class)),
+ MethodHandles.identity(int.class), null);
} catch (IllegalArgumentException iae) {
assertEquals("iterated loop body must not be null", iae.getMessage());
caught = true;
@@ -368,6 +400,26 @@
assertTrue(caught);
}
+ @Test
+ public static void testIterateVoidIterator() {
+ boolean caught = false;
+ MethodType v = methodType(void.class);
+ try {
+ MethodHandles.iteratedLoop(MethodHandles.empty(v), null, MethodHandles.empty(v));
+ } catch(IllegalArgumentException iae) {
+ assertEquals("iteratedLoop first argument must have Iterator return type", iae.getMessage());
+ caught = true;
+ }
+ assertTrue(caught);
+ }
+
+ @Test
+ public static void testIterateVoidInit() throws Throwable {
+ MethodHandle loop = MethodHandles.iteratedLoop(null, Iterate.MH_voidInit, Iterate.MH_printStep);
+ assertEquals(Iterate.MT_print, loop.type());
+ loop.invoke(Arrays.asList("hello", "world"));
+ }
+
static class Empty {
static void f() { }
@@ -604,6 +656,10 @@
private int i = 0;
+ void voidInit(int k) {
+ // empty
+ }
+
void voidBody(int k) {
++i;
}
@@ -623,6 +679,7 @@
static final MethodType MT_zipInitZip = methodType(List.class, Iterator.class, Iterator.class);
static final MethodType MT_zipPred = methodType(boolean.class, List.class, Iterator.class, Iterator.class);
static final MethodType MT_zipStep = methodType(List.class, List.class, Iterator.class, Iterator.class);
+ static final MethodType MT_voidInit = methodType(void.class, int.class);
static final MethodType MT_voidBody = methodType(void.class, int.class);
static final MethodType MT_voidPred = methodType(boolean.class, int.class);
@@ -635,6 +692,7 @@
static final MethodHandle MH_zipInitZip;
static final MethodHandle MH_zipPred;
static final MethodHandle MH_zipStep;
+ static final MethodHandle MH_voidInit;
static final MethodHandle MH_voidBody;
static final MethodHandle MH_voidPred;
@@ -654,6 +712,7 @@
MH_zipInitZip = LOOKUP.findStatic(WHILE, "zipInitZip", MT_zipInitZip);
MH_zipPred = LOOKUP.findStatic(WHILE, "zipPred", MT_zipPred);
MH_zipStep = LOOKUP.findStatic(WHILE, "zipStep", MT_zipStep);
+ MH_voidInit = LOOKUP.findVirtual(WHILE, "voidInit", MT_voidInit);
MH_voidBody = LOOKUP.findVirtual(WHILE, "voidBody", MT_voidBody);
MH_voidPred = LOOKUP.findVirtual(WHILE, "voidPred", MT_voidPred);
} catch (Exception e) {
@@ -768,6 +827,10 @@
System.out.print(s);
}
+ static void voidInit() {
+ // empty
+ }
+
static final Class<Iterate> ITERATE = Iterate.class;
static final MethodType MT_sumIterator = methodType(Iterator.class, Integer[].class);
@@ -783,6 +846,8 @@
static final MethodType MT_mapStep = methodType(List.class, String.class, List.class, List.class);
static final MethodType MT_printStep = methodType(void.class, String.class, List.class);
+ static final MethodType MT_voidInit = methodType(void.class);
+
static final MethodHandle MH_sumIterator;
static final MethodHandle MH_sumInit;
static final MethodHandle MH_sumStep;
@@ -797,6 +862,8 @@
static final MethodHandle MH_mapInit;
static final MethodHandle MH_mapStep;
+ static final MethodHandle MH_voidInit;
+
static final MethodType MT_sum = methodType(int.class, Integer[].class);
static final MethodType MT_reverse = methodType(List.class, List.class);
static final MethodType MT_length = methodType(int.class, List.class);
@@ -815,6 +882,7 @@
MH_mapInit = LOOKUP.findStatic(ITERATE, "mapInit", MT_mapInit);
MH_mapStep = LOOKUP.findStatic(ITERATE, "mapStep", MT_mapStep);
MH_printStep = LOOKUP.findStatic(ITERATE, "printStep", MT_printStep);
+ MH_voidInit = LOOKUP.findStatic(ITERATE, "voidInit", MT_voidInit);
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
--- a/jdk/test/java/net/NetworkInterface/NetworkInterfaceStreamTest.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/java/net/NetworkInterface/NetworkInterfaceStreamTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -28,7 +28,6 @@
* @build java.base/java.util.stream.OpTestCase
* @run testng/othervm NetworkInterfaceStreamTest
* @run testng/othervm -Djava.net.preferIPv4Stack=true NetworkInterfaceStreamTest
- * @key intermittent
*/
import org.testng.annotations.Test;
@@ -52,21 +51,27 @@
public void testNetworkInterfaces() throws SocketException {
Supplier<Stream<NetworkInterface>> ss = () -> {
try {
- return NetworkInterface.networkInterfaces();
+ return NetworkInterface.networkInterfaces()
+ .filter(ni -> isIncluded(ni));
}
catch (SocketException e) {
throw new RuntimeException(e);
}
};
- Collection<NetworkInterface> expected = Collections.list(NetworkInterface.getNetworkInterfaces());
+ Collection<NetworkInterface> enums = Collections.list(NetworkInterface.getNetworkInterfaces());
+ Collection<NetworkInterface> expected = new ArrayList<>();
+ enums.forEach(ni -> {
+ if (isIncluded(ni)) {
+ expected.add(ni);
+ }
+ });
withData(TestData.Factory.ofSupplier("Top-level network interfaces", ss))
.stream(s -> s)
.expectedResult(expected)
.exercise();
}
-
private Collection<NetworkInterface> getAllNetworkInterfaces() throws SocketException {
Collection<NetworkInterface> anis = new ArrayList<>();
for (NetworkInterface ni : Collections.list(NetworkInterface.getNetworkInterfaces())) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/HpackDriver.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016, 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 8153353
+ * @modules java.httpclient/sun.net.httpclient.hpack
+ * @key randomness
+ * @compile/module=java.httpclient sun/net/httpclient/hpack/SpecHelper.java
+ * @compile/module=java.httpclient sun/net/httpclient/hpack/TestHelper.java
+ * @compile/module=java.httpclient sun/net/httpclient/hpack/BuffersTestingKit.java
+ * @run testng/othervm -XaddReads:java.httpclient=ALL-UNNAMED java.httpclient/sun.net.httpclient.hpack.BinaryPrimitivesTest
+ * @run testng/othervm -XaddReads:java.httpclient=ALL-UNNAMED java.httpclient/sun.net.httpclient.hpack.CircularBufferTest
+ * @run testng/othervm -XaddReads:java.httpclient=ALL-UNNAMED java.httpclient/sun.net.httpclient.hpack.DecoderTest
+ * @run testng/othervm -XaddReads:java.httpclient=ALL-UNNAMED java.httpclient/sun.net.httpclient.hpack.EncoderTest
+ * @run testng/othervm -XaddReads:java.httpclient=ALL-UNNAMED java.httpclient/sun.net.httpclient.hpack.HeaderTableTest
+ * @run testng/othervm -XaddReads:java.httpclient=ALL-UNNAMED java.httpclient/sun.net.httpclient.hpack.HuffmanTest
+ * @run testng/othervm -XaddReads:java.httpclient=ALL-UNNAMED java.httpclient/sun.net.httpclient.hpack.TestHelper
+ */
+public class HpackDriver { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/BinaryPrimitivesTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 2014, 2016, 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.
+ */
+package sun.net.httpclient.hpack;
+
+import org.testng.annotations.Test;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+import static sun.net.httpclient.hpack.BuffersTestingKit.*;
+import static sun.net.httpclient.hpack.TestHelper.newRandom;
+
+//
+// Some of the tests below overlap in what they test. This allows to diagnose
+// bugs quicker and with less pain by simply ruling out common working bits.
+//
+public final class BinaryPrimitivesTest {
+
+ private final Random rnd = newRandom();
+
+ @Test
+ public void integerRead1() {
+ verifyRead(bytes(0b00011111, 0b10011010, 0b00001010), 1337, 5);
+ }
+
+ @Test
+ public void integerRead2() {
+ verifyRead(bytes(0b00001010), 10, 5);
+ }
+
+ @Test
+ public void integerRead3() {
+ verifyRead(bytes(0b00101010), 42, 8);
+ }
+
+ @Test
+ public void integerWrite1() {
+ verifyWrite(bytes(0b00011111, 0b10011010, 0b00001010), 1337, 5);
+ }
+
+ @Test
+ public void integerWrite2() {
+ verifyWrite(bytes(0b00001010), 10, 5);
+ }
+
+ @Test
+ public void integerWrite3() {
+ verifyWrite(bytes(0b00101010), 42, 8);
+ }
+
+ //
+ // Since readInteger(x) is the inverse of writeInteger(x), thus:
+ //
+ // for all x: readInteger(writeInteger(x)) == x
+ //
+ @Test
+ public void integerIdentity() {
+ final int MAX_VALUE = 1 << 22;
+ int totalCases = 0;
+ int maxFilling = 0;
+ IntegerReader r = new IntegerReader();
+ IntegerWriter w = new IntegerWriter();
+ ByteBuffer buf = ByteBuffer.allocate(8);
+ for (int N = 1; N < 9; N++) {
+ for (int expected = 0; expected <= MAX_VALUE; expected++) {
+ w.reset().configure(expected, N, 1).write(buf);
+ buf.flip();
+ totalCases++;
+ maxFilling = Math.max(maxFilling, buf.remaining());
+ r.reset().configure(N).read(buf);
+ assertEquals(r.get(), expected);
+ buf.clear();
+ }
+ }
+ System.out.printf("totalCases: %,d, maxFilling: %,d, maxValue: %,d%n",
+ totalCases, maxFilling, MAX_VALUE);
+ }
+
+ @Test
+ public void integerReadChunked() {
+ final int NUM_TESTS = 1024;
+ IntegerReader r = new IntegerReader();
+ ByteBuffer bb = ByteBuffer.allocate(8);
+ IntegerWriter w = new IntegerWriter();
+ for (int i = 0; i < NUM_TESTS; i++) {
+ final int N = 1 + rnd.nextInt(8);
+ final int expected = rnd.nextInt(Integer.MAX_VALUE) + 1;
+ w.reset().configure(expected, N, rnd.nextInt()).write(bb);
+ bb.flip();
+
+ forEachSplit(bb,
+ (buffers) -> {
+ Iterable<? extends ByteBuffer> buf = relocateBuffers(injectEmptyBuffers(buffers));
+ r.configure(N);
+ for (ByteBuffer b : buf) {
+ r.read(b);
+ }
+ assertEquals(r.get(), expected);
+ r.reset();
+ });
+ bb.clear();
+ }
+ }
+
+ // FIXME: use maxValue in the test
+
+ @Test
+ // FIXME: tune values for better coverage
+ public void integerWriteChunked() {
+ ByteBuffer bb = ByteBuffer.allocate(6);
+ IntegerWriter w = new IntegerWriter();
+ IntegerReader r = new IntegerReader();
+ for (int i = 0; i < 1024; i++) { // number of tests
+ final int N = 1 + rnd.nextInt(8);
+ final int payload = rnd.nextInt(255);
+ final int expected = rnd.nextInt(Integer.MAX_VALUE) + 1;
+
+ forEachSplit(bb,
+ (buffers) -> {
+ List<ByteBuffer> buf = new ArrayList<>();
+ relocateBuffers(injectEmptyBuffers(buffers)).forEach(buf::add);
+ boolean written = false;
+ w.configure(expected, N, payload); // TODO: test for payload it can be read after written
+ for (ByteBuffer b : buf) {
+ int pos = b.position();
+ written = w.write(b);
+ b.position(pos);
+ }
+ if (!written) {
+ fail("please increase bb size");
+ }
+ r.configure(N).read(concat(buf));
+ // TODO: check payload here
+ assertEquals(r.get(), expected);
+ w.reset();
+ r.reset();
+ bb.clear();
+ });
+ }
+ }
+
+
+ //
+ // Since readString(x) is the inverse of writeString(x), thus:
+ //
+ // for all x: readString(writeString(x)) == x
+ //
+ @Test
+ public void stringIdentity() {
+ final int MAX_STRING_LENGTH = 4096;
+ ByteBuffer bytes = ByteBuffer.allocate(MAX_STRING_LENGTH + 6); // it takes 6 bytes to encode string length of Integer.MAX_VALUE
+ CharBuffer chars = CharBuffer.allocate(MAX_STRING_LENGTH);
+ StringReader reader = new StringReader();
+ StringWriter writer = new StringWriter();
+ for (int len = 0; len <= MAX_STRING_LENGTH; len++) {
+ for (int i = 0; i < 64; i++) {
+ // not so much "test in isolation", I know... we're testing .reset() as well
+ bytes.clear();
+ chars.clear();
+
+ byte[] b = new byte[len];
+ rnd.nextBytes(b);
+
+ String expected = new String(b, StandardCharsets.ISO_8859_1); // reference string
+
+ boolean written = writer
+ .configure(CharBuffer.wrap(expected), 0, expected.length(), false)
+ .write(bytes);
+
+ if (!written) {
+ fail("please increase 'bytes' size");
+ }
+ bytes.flip();
+ reader.read(bytes, chars);
+ chars.flip();
+ assertEquals(chars.toString(), expected);
+ reader.reset();
+ writer.reset();
+ }
+ }
+ }
+
+// @Test
+// public void huffmanStringWriteChunked() {
+// fail();
+// }
+//
+// @Test
+// public void huffmanStringReadChunked() {
+// fail();
+// }
+
+ @Test
+ public void stringWriteChunked() {
+ final int MAX_STRING_LENGTH = 8;
+ final ByteBuffer bytes = ByteBuffer.allocate(MAX_STRING_LENGTH + 6);
+ final CharBuffer chars = CharBuffer.allocate(MAX_STRING_LENGTH);
+ final StringReader reader = new StringReader();
+ final StringWriter writer = new StringWriter();
+ for (int len = 0; len <= MAX_STRING_LENGTH; len++) {
+
+ byte[] b = new byte[len];
+ rnd.nextBytes(b);
+
+ String expected = new String(b, StandardCharsets.ISO_8859_1); // reference string
+
+ forEachSplit(bytes, (buffers) -> {
+ writer.configure(expected, 0, expected.length(), false);
+ boolean written = false;
+ for (ByteBuffer buf : buffers) {
+ int p0 = buf.position();
+ written = writer.write(buf);
+ buf.position(p0);
+ }
+ if (!written) {
+ fail("please increase 'bytes' size");
+ }
+ reader.read(concat(buffers), chars);
+ chars.flip();
+ assertEquals(chars.toString(), expected);
+ reader.reset();
+ writer.reset();
+ chars.clear();
+ bytes.clear();
+ });
+ }
+ }
+
+ @Test
+ public void stringReadChunked() {
+ final int MAX_STRING_LENGTH = 16;
+ final ByteBuffer bytes = ByteBuffer.allocate(MAX_STRING_LENGTH + 6);
+ final CharBuffer chars = CharBuffer.allocate(MAX_STRING_LENGTH);
+ final StringReader reader = new StringReader();
+ final StringWriter writer = new StringWriter();
+ for (int len = 0; len <= MAX_STRING_LENGTH; len++) {
+
+ byte[] b = new byte[len];
+ rnd.nextBytes(b);
+
+ String expected = new String(b, StandardCharsets.ISO_8859_1); // reference string
+
+ boolean written = writer
+ .configure(CharBuffer.wrap(expected), 0, expected.length(), false)
+ .write(bytes);
+ writer.reset();
+
+ if (!written) {
+ fail("please increase 'bytes' size");
+ }
+ bytes.flip();
+
+ forEachSplit(bytes, (buffers) -> {
+ for (ByteBuffer buf : buffers) {
+ int p0 = buf.position();
+ reader.read(buf, chars);
+ buf.position(p0);
+ }
+ chars.flip();
+ assertEquals(chars.toString(), expected);
+ reader.reset();
+ chars.clear();
+ });
+
+ bytes.clear();
+ }
+ }
+
+// @Test
+// public void test_Huffman_String_Identity() {
+// StringWriter writer = new StringWriter();
+// StringReader reader = new StringReader();
+// // 256 * 8 gives 2048 bits in case of plain 8 bit coding
+// // 256 * 30 gives you 7680 bits or 960 bytes in case of almost
+// // improbable event of 256 30 bits symbols in a row
+// ByteBuffer binary = ByteBuffer.allocate(960);
+// CharBuffer text = CharBuffer.allocate(960 / 5); // 5 = minimum code length
+// for (int len = 0; len < 128; len++) {
+// for (int i = 0; i < 256; i++) {
+// // not so much "test in isolation", I know...
+// binary.clear();
+//
+// byte[] bytes = new byte[len];
+// rnd.nextBytes(bytes);
+//
+// String s = new String(bytes, StandardCharsets.ISO_8859_1);
+//
+// writer.write(CharBuffer.wrap(s), binary, true);
+// binary.flip();
+// reader.read(binary, text);
+// text.flip();
+// assertEquals(text.toString(), s);
+// }
+// }
+// }
+
+ // TODO: atomic failures: e.g. readonly/overflow
+
+ private static byte[] bytes(int... data) {
+ byte[] bytes = new byte[data.length];
+ for (int i = 0; i < data.length; i++) {
+ bytes[i] = (byte) data[i];
+ }
+ return bytes;
+ }
+
+ private static void verifyRead(byte[] data, int expected, int N) {
+ ByteBuffer buf = ByteBuffer.wrap(data, 0, data.length);
+ IntegerReader reader = new IntegerReader();
+ reader.configure(N).read(buf);
+ assertEquals(expected, reader.get());
+ }
+
+ private void verifyWrite(byte[] expected, int data, int N) {
+ IntegerWriter w = new IntegerWriter();
+ ByteBuffer buf = ByteBuffer.allocate(2 * expected.length);
+ w.configure(data, N, 1).write(buf);
+ buf.flip();
+ assertEquals(ByteBuffer.wrap(expected), buf);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/BuffersTestingKit.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2015, 2016, 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.
+ */
+package sun.net.httpclient.hpack;
+
+import java.nio.ByteBuffer;
+import java.util.*;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+import static java.nio.ByteBuffer.allocate;
+
+public final class BuffersTestingKit {
+
+ /**
+ * Relocates a {@code [position, limit)} region of the given buffer to
+ * corresponding region in a new buffer starting with provided {@code
+ * newPosition}.
+ *
+ * <p> Might be useful to make sure ByteBuffer's users do not rely on any
+ * absolute positions, but solely on what's reported by position(), limit().
+ *
+ * <p> The contents between the given buffer and the returned one are not
+ * shared.
+ */
+ public static ByteBuffer relocate(ByteBuffer buffer, int newPosition,
+ int newCapacity) {
+ int oldPosition = buffer.position();
+ int oldLimit = buffer.limit();
+
+ if (newPosition + oldLimit - oldPosition > newCapacity) {
+ throw new IllegalArgumentException();
+ }
+
+ ByteBuffer result;
+ if (buffer.isDirect()) {
+ result = ByteBuffer.allocateDirect(newCapacity);
+ } else {
+ result = allocate(newCapacity);
+ }
+
+ result.position(newPosition);
+ result.put(buffer).limit(result.position()).position(newPosition);
+ buffer.position(oldPosition);
+
+ if (buffer.isReadOnly()) {
+ return result.asReadOnlyBuffer();
+ }
+ return result;
+ }
+
+ public static Iterable<? extends ByteBuffer> relocateBuffers(
+ Iterable<? extends ByteBuffer> source) {
+ return () ->
+ new Iterator<ByteBuffer>() {
+
+ private final Iterator<? extends ByteBuffer> it = source.iterator();
+
+ @Override
+ public boolean hasNext() {
+ return it.hasNext();
+ }
+
+ @Override
+ public ByteBuffer next() {
+ ByteBuffer buf = it.next();
+ int remaining = buf.remaining();
+ int newCapacity = remaining + random.nextInt(17);
+ int newPosition = random.nextInt(newCapacity - remaining + 1);
+ return relocate(buf, newPosition, newCapacity);
+ }
+ };
+ }
+
+ // TODO: not always of size 0 (it's fine for buffer to report !b.hasRemaining())
+ public static Iterable<? extends ByteBuffer> injectEmptyBuffers(
+ Iterable<? extends ByteBuffer> source) {
+ return injectEmptyBuffers(source, () -> allocate(0));
+ }
+
+ public static Iterable<? extends ByteBuffer> injectEmptyBuffers(
+ Iterable<? extends ByteBuffer> source,
+ Supplier<? extends ByteBuffer> emptyBufferFactory) {
+
+ return () ->
+ new Iterator<ByteBuffer>() {
+
+ private final Iterator<? extends ByteBuffer> it = source.iterator();
+ private ByteBuffer next = calculateNext();
+
+ private ByteBuffer calculateNext() {
+ if (random.nextBoolean()) {
+ return emptyBufferFactory.get();
+ } else if (it.hasNext()) {
+ return it.next();
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public boolean hasNext() {
+ return next != null;
+ }
+
+ @Override
+ public ByteBuffer next() {
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+ ByteBuffer next = this.next;
+ this.next = calculateNext();
+ return next;
+ }
+ };
+ }
+
+ public static ByteBuffer concat(Iterable<? extends ByteBuffer> split) {
+ return concat(split, ByteBuffer::allocate);
+ }
+
+ public static ByteBuffer concat(Iterable<? extends ByteBuffer> split,
+ Function<? super Integer, ? extends ByteBuffer> concatBufferFactory) {
+ int size = 0;
+ for (ByteBuffer bb : split) {
+ size += bb.remaining();
+ }
+
+ ByteBuffer result = concatBufferFactory.apply(size);
+ for (ByteBuffer bb : split) {
+ result.put(bb);
+ }
+
+ result.flip();
+ return result;
+ }
+
+ public static void forEachSplit(ByteBuffer bb,
+ Consumer<? super Iterable<? extends ByteBuffer>> action) {
+ forEachSplit(bb.remaining(),
+ (lengths) -> {
+ int end = bb.position();
+ List<ByteBuffer> buffers = new LinkedList<>();
+ for (int len : lengths) {
+ ByteBuffer d = bb.duplicate();
+ d.position(end);
+ d.limit(end + len);
+ end += len;
+ buffers.add(d);
+ }
+ action.accept(buffers);
+ });
+ }
+
+ private static void forEachSplit(int n, Consumer<? super Iterable<? extends Integer>> action) {
+ forEachSplit(n, new Stack<>(), action);
+ }
+
+ private static void forEachSplit(int n, Stack<Integer> path,
+ Consumer<? super Iterable<? extends Integer>> action) {
+ if (n == 0) {
+ action.accept(path);
+ } else {
+ for (int i = 1; i <= n; i++) {
+ path.push(i);
+ forEachSplit(n - i, path, action);
+ path.pop();
+ }
+ }
+ }
+
+ private static final Random random = new Random();
+
+ private BuffersTestingKit() {
+ throw new InternalError();
+ }
+
+// public static void main(String[] args) {
+//
+// List<ByteBuffer> buffers = Arrays.asList(
+// (ByteBuffer) allocate(3).position(1).limit(2),
+// allocate(0),
+// allocate(7));
+//
+// Iterable<? extends ByteBuffer> buf = relocateBuffers(injectEmptyBuffers(buffers));
+// List<ByteBuffer> result = new ArrayList<>();
+// buf.forEach(result::add);
+// System.out.println(result);
+// }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/CircularBufferTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+package sun.net.httpclient.hpack;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import sun.net.httpclient.hpack.HeaderTable.CircularBuffer;
+
+import java.util.Queue;
+import java.util.Random;
+import java.util.concurrent.ArrayBlockingQueue;
+
+import static org.testng.Assert.assertEquals;
+import static sun.net.httpclient.hpack.TestHelper.newRandom;
+
+public final class CircularBufferTest {
+
+ private final Random r = newRandom();
+
+ @BeforeClass
+ public void setUp() {
+ r.setSeed(System.currentTimeMillis());
+ }
+
+ @Test
+ public void queue() {
+ for (int capacity = 1; capacity <= 2048; capacity++) {
+ queueOnce(capacity, 32);
+ }
+ }
+
+ @Test
+ public void resize() {
+ for (int capacity = 1; capacity <= 4096; capacity++) {
+ resizeOnce(capacity);
+ }
+ }
+
+ @Test
+ public void downSizeEmptyBuffer() {
+ CircularBuffer<Integer> buffer = new CircularBuffer<>(16);
+ buffer.resize(15);
+ }
+
+ private void resizeOnce(int capacity) {
+
+ int nextNumberToPut = 0;
+
+ Queue<Integer> referenceQueue = new ArrayBlockingQueue<>(capacity);
+ CircularBuffer<Integer> buffer = new CircularBuffer<>(capacity);
+
+ // Fill full, so the next add will wrap
+ for (int i = 0; i < capacity; i++, nextNumberToPut++) {
+ buffer.add(nextNumberToPut);
+ referenceQueue.add(nextNumberToPut);
+ }
+ int gets = r.nextInt(capacity); // [0, capacity)
+ for (int i = 0; i < gets; i++) {
+ referenceQueue.poll();
+ buffer.remove();
+ }
+ int puts = r.nextInt(gets + 1); // [0, gets]
+ for (int i = 0; i < puts; i++, nextNumberToPut++) {
+ buffer.add(nextNumberToPut);
+ referenceQueue.add(nextNumberToPut);
+ }
+
+ Integer[] expected = referenceQueue.toArray(new Integer[0]);
+ buffer.resize(expected.length);
+
+ assertEquals(buffer.elements, expected);
+ }
+
+ private void queueOnce(int capacity, int numWraps) {
+
+ Queue<Integer> referenceQueue = new ArrayBlockingQueue<>(capacity);
+ CircularBuffer<Integer> buffer = new CircularBuffer<>(capacity);
+
+ int nextNumberToPut = 0;
+ int totalPuts = 0;
+ int putsLimit = capacity * numWraps;
+ int remainingCapacity = capacity;
+ int size = 0;
+
+ while (totalPuts < putsLimit) {
+ assert remainingCapacity + size == capacity;
+ int puts = r.nextInt(remainingCapacity + 1); // [0, remainingCapacity]
+ remainingCapacity -= puts;
+ size += puts;
+ for (int i = 0; i < puts; i++, nextNumberToPut++) {
+ referenceQueue.add(nextNumberToPut);
+ buffer.add(nextNumberToPut);
+ }
+ totalPuts += puts;
+ int gets = r.nextInt(size + 1); // [0, size]
+ size -= gets;
+ remainingCapacity += gets;
+ for (int i = 0; i < gets; i++) {
+ Integer expected = referenceQueue.poll();
+ Integer actual = buffer.remove();
+ assertEquals(actual, expected);
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/DecoderTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,595 @@
+/*
+ * Copyright (c) 2015, 2016, 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.
+ */
+package sun.net.httpclient.hpack;
+
+import org.testng.annotations.Test;
+
+import java.io.UncheckedIOException;
+import java.net.ProtocolException;
+import java.nio.ByteBuffer;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static sun.net.httpclient.hpack.TestHelper.*;
+
+public final class DecoderTest {
+
+ //
+ // http://tools.ietf.org/html/rfc7541#appendix-C.2.1
+ //
+ @Test
+ public void example1() {
+ // @formatter:off
+ test("400a 6375 7374 6f6d 2d6b 6579 0d63 7573\n" +
+ "746f 6d2d 6865 6164 6572",
+
+ "[ 1] (s = 55) custom-key: custom-header\n" +
+ " Table size: 55",
+
+ "custom-key: custom-header");
+ // @formatter:on
+ }
+
+ //
+ // http://tools.ietf.org/html/rfc7541#appendix-C.2.2
+ //
+ @Test
+ public void example2() {
+ // @formatter:off
+ test("040c 2f73 616d 706c 652f 7061 7468",
+ "empty.",
+ ":path: /sample/path");
+ // @formatter:on
+ }
+
+ //
+ // http://tools.ietf.org/html/rfc7541#appendix-C.2.3
+ //
+ @Test
+ public void example3() {
+ // @formatter:off
+ test("1008 7061 7373 776f 7264 0673 6563 7265\n" +
+ "74",
+ "empty.",
+ "password: secret");
+ // @formatter:on
+ }
+
+ //
+ // http://tools.ietf.org/html/rfc7541#appendix-C.2.4
+ //
+ @Test
+ public void example4() {
+ // @formatter:off
+ test("82",
+ "empty.",
+ ":method: GET");
+ // @formatter:on
+ }
+
+ //
+ // http://tools.ietf.org/html/rfc7541#appendix-C.3
+ //
+ @Test
+ public void example5() {
+ // @formatter:off
+ Decoder d = new Decoder(256);
+
+ test(d, "8286 8441 0f77 7777 2e65 7861 6d70 6c65\n" +
+ "2e63 6f6d",
+
+ "[ 1] (s = 57) :authority: www.example.com\n" +
+ " Table size: 57",
+
+ ":method: GET\n" +
+ ":scheme: http\n" +
+ ":path: /\n" +
+ ":authority: www.example.com");
+
+ test(d, "8286 84be 5808 6e6f 2d63 6163 6865",
+
+ "[ 1] (s = 53) cache-control: no-cache\n" +
+ "[ 2] (s = 57) :authority: www.example.com\n" +
+ " Table size: 110",
+
+ ":method: GET\n" +
+ ":scheme: http\n" +
+ ":path: /\n" +
+ ":authority: www.example.com\n" +
+ "cache-control: no-cache");
+
+ test(d, "8287 85bf 400a 6375 7374 6f6d 2d6b 6579\n" +
+ "0c63 7573 746f 6d2d 7661 6c75 65",
+
+ "[ 1] (s = 54) custom-key: custom-value\n" +
+ "[ 2] (s = 53) cache-control: no-cache\n" +
+ "[ 3] (s = 57) :authority: www.example.com\n" +
+ " Table size: 164",
+
+ ":method: GET\n" +
+ ":scheme: https\n" +
+ ":path: /index.html\n" +
+ ":authority: www.example.com\n" +
+ "custom-key: custom-value");
+
+ // @formatter:on
+ }
+
+ //
+ // http://tools.ietf.org/html/rfc7541#appendix-C.4
+ //
+ @Test
+ public void example6() {
+ // @formatter:off
+ Decoder d = new Decoder(256);
+
+ test(d, "8286 8441 8cf1 e3c2 e5f2 3a6b a0ab 90f4\n" +
+ "ff",
+
+ "[ 1] (s = 57) :authority: www.example.com\n" +
+ " Table size: 57",
+
+ ":method: GET\n" +
+ ":scheme: http\n" +
+ ":path: /\n" +
+ ":authority: www.example.com");
+
+ test(d, "8286 84be 5886 a8eb 1064 9cbf",
+
+ "[ 1] (s = 53) cache-control: no-cache\n" +
+ "[ 2] (s = 57) :authority: www.example.com\n" +
+ " Table size: 110",
+
+ ":method: GET\n" +
+ ":scheme: http\n" +
+ ":path: /\n" +
+ ":authority: www.example.com\n" +
+ "cache-control: no-cache");
+
+ test(d, "8287 85bf 4088 25a8 49e9 5ba9 7d7f 8925\n" +
+ "a849 e95b b8e8 b4bf",
+
+ "[ 1] (s = 54) custom-key: custom-value\n" +
+ "[ 2] (s = 53) cache-control: no-cache\n" +
+ "[ 3] (s = 57) :authority: www.example.com\n" +
+ " Table size: 164",
+
+ ":method: GET\n" +
+ ":scheme: https\n" +
+ ":path: /index.html\n" +
+ ":authority: www.example.com\n" +
+ "custom-key: custom-value");
+ // @formatter:on
+ }
+
+ //
+ // http://tools.ietf.org/html/rfc7541#appendix-C.5
+ //
+ @Test
+ public void example7() {
+ // @formatter:off
+ Decoder d = new Decoder(256);
+
+ test(d, "4803 3330 3258 0770 7269 7661 7465 611d\n" +
+ "4d6f 6e2c 2032 3120 4f63 7420 3230 3133\n" +
+ "2032 303a 3133 3a32 3120 474d 546e 1768\n" +
+ "7474 7073 3a2f 2f77 7777 2e65 7861 6d70\n" +
+ "6c65 2e63 6f6d",
+
+ "[ 1] (s = 63) location: https://www.example.com\n" +
+ "[ 2] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT\n" +
+ "[ 3] (s = 52) cache-control: private\n" +
+ "[ 4] (s = 42) :status: 302\n" +
+ " Table size: 222",
+
+ ":status: 302\n" +
+ "cache-control: private\n" +
+ "date: Mon, 21 Oct 2013 20:13:21 GMT\n" +
+ "location: https://www.example.com");
+
+ test(d, "4803 3330 37c1 c0bf",
+
+ "[ 1] (s = 42) :status: 307\n" +
+ "[ 2] (s = 63) location: https://www.example.com\n" +
+ "[ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT\n" +
+ "[ 4] (s = 52) cache-control: private\n" +
+ " Table size: 222",
+
+ ":status: 307\n" +
+ "cache-control: private\n" +
+ "date: Mon, 21 Oct 2013 20:13:21 GMT\n" +
+ "location: https://www.example.com");
+
+ test(d, "88c1 611d 4d6f 6e2c 2032 3120 4f63 7420\n" +
+ "3230 3133 2032 303a 3133 3a32 3220 474d\n" +
+ "54c0 5a04 677a 6970 7738 666f 6f3d 4153\n" +
+ "444a 4b48 514b 425a 584f 5157 454f 5049\n" +
+ "5541 5851 5745 4f49 553b 206d 6178 2d61\n" +
+ "6765 3d33 3630 303b 2076 6572 7369 6f6e\n" +
+ "3d31",
+
+ "[ 1] (s = 98) set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1\n" +
+ "[ 2] (s = 52) content-encoding: gzip\n" +
+ "[ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:22 GMT\n" +
+ " Table size: 215",
+
+ ":status: 200\n" +
+ "cache-control: private\n" +
+ "date: Mon, 21 Oct 2013 20:13:22 GMT\n" +
+ "location: https://www.example.com\n" +
+ "content-encoding: gzip\n" +
+ "set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1");
+ // @formatter:on
+ }
+
+ //
+ // http://tools.ietf.org/html/rfc7541#appendix-C.6
+ //
+ @Test
+ public void example8() {
+ // @formatter:off
+ Decoder d = new Decoder(256);
+
+ test(d, "4882 6402 5885 aec3 771a 4b61 96d0 7abe\n" +
+ "9410 54d4 44a8 2005 9504 0b81 66e0 82a6\n" +
+ "2d1b ff6e 919d 29ad 1718 63c7 8f0b 97c8\n" +
+ "e9ae 82ae 43d3",
+
+ "[ 1] (s = 63) location: https://www.example.com\n" +
+ "[ 2] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT\n" +
+ "[ 3] (s = 52) cache-control: private\n" +
+ "[ 4] (s = 42) :status: 302\n" +
+ " Table size: 222",
+
+ ":status: 302\n" +
+ "cache-control: private\n" +
+ "date: Mon, 21 Oct 2013 20:13:21 GMT\n" +
+ "location: https://www.example.com");
+
+ test(d, "4883 640e ffc1 c0bf",
+
+ "[ 1] (s = 42) :status: 307\n" +
+ "[ 2] (s = 63) location: https://www.example.com\n" +
+ "[ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT\n" +
+ "[ 4] (s = 52) cache-control: private\n" +
+ " Table size: 222",
+
+ ":status: 307\n" +
+ "cache-control: private\n" +
+ "date: Mon, 21 Oct 2013 20:13:21 GMT\n" +
+ "location: https://www.example.com");
+
+ test(d, "88c1 6196 d07a be94 1054 d444 a820 0595\n" +
+ "040b 8166 e084 a62d 1bff c05a 839b d9ab\n" +
+ "77ad 94e7 821d d7f2 e6c7 b335 dfdf cd5b\n" +
+ "3960 d5af 2708 7f36 72c1 ab27 0fb5 291f\n" +
+ "9587 3160 65c0 03ed 4ee5 b106 3d50 07",
+
+ "[ 1] (s = 98) set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1\n" +
+ "[ 2] (s = 52) content-encoding: gzip\n" +
+ "[ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:22 GMT\n" +
+ " Table size: 215",
+
+ ":status: 200\n" +
+ "cache-control: private\n" +
+ "date: Mon, 21 Oct 2013 20:13:22 GMT\n" +
+ "location: https://www.example.com\n" +
+ "content-encoding: gzip\n" +
+ "set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1");
+ // @formatter:on
+ }
+
+ @Test
+ // One of responses from Apache Server that helped to catch a bug
+ public void testX() {
+ Decoder d = new Decoder(4096);
+ // @formatter:off
+ test(d, "3fe1 1f88 6196 d07a be94 03ea 693f 7504\n" +
+ "00b6 a05c b827 2e32 fa98 b46f 769e 86b1\n" +
+ "9272 b025 da5c 2ea9 fd70 a8de 7fb5 3556\n" +
+ "5ab7 6ece c057 02e2 2ad2 17bf 6c96 d07a\n" +
+ "be94 0854 cb6d 4a08 0075 40bd 71b6 6e05\n" +
+ "a531 68df 0f13 8efe 4522 cd32 21b6 5686\n" +
+ "eb23 781f cf52 848f d24a 8f0f 0d02 3435\n" +
+ "5f87 497c a589 d34d 1f",
+
+ "[ 1] (s = 53) content-type: text/html\n" +
+ "[ 2] (s = 50) accept-ranges: bytes\n" +
+ "[ 3] (s = 74) last-modified: Mon, 11 Jun 2007 18:53:14 GMT\n" +
+ "[ 4] (s = 77) server: Apache/2.4.17 (Unix) OpenSSL/1.0.2e-dev\n" +
+ "[ 5] (s = 65) date: Mon, 09 Nov 2015 16:26:39 GMT\n" +
+ " Table size: 319",
+
+ ":status: 200\n" +
+ "date: Mon, 09 Nov 2015 16:26:39 GMT\n" +
+ "server: Apache/2.4.17 (Unix) OpenSSL/1.0.2e-dev\n" +
+ "last-modified: Mon, 11 Jun 2007 18:53:14 GMT\n" +
+ "etag: \"2d-432a5e4a73a80\"\n" +
+ "accept-ranges: bytes\n" +
+ "content-length: 45\n" +
+ "content-type: text/html");
+ // @formatter:on
+ }
+
+ //
+ // This test is missing in the spec
+ //
+ @Test
+ public void sizeUpdate() {
+ Decoder d = new Decoder(4096);
+ assertEquals(d.getTable().maxSize(), 4096);
+ d.decode(ByteBuffer.wrap(new byte[]{0b00111110}), true, nopCallback()); // newSize = 30
+ assertEquals(d.getTable().maxSize(), 30);
+ }
+
+ @Test
+ public void incorrectSizeUpdate() {
+ ByteBuffer b = ByteBuffer.allocate(8);
+ Encoder e = new Encoder(8192) {
+ @Override
+ protected int calculateCapacity(int maxCapacity) {
+ return maxCapacity;
+ }
+ };
+ e.header("a", "b");
+ e.encode(b);
+ b.flip();
+ {
+ Decoder d = new Decoder(4096);
+ UncheckedIOException ex = assertVoidThrows(UncheckedIOException.class,
+ () -> d.decode(b, true, (name, value) -> { }));
+
+ assertNotNull(ex.getCause());
+ assertEquals(ex.getCause().getClass(), ProtocolException.class);
+ }
+ b.flip();
+ {
+ Decoder d = new Decoder(4096);
+ UncheckedIOException ex = assertVoidThrows(UncheckedIOException.class,
+ () -> d.decode(b, false, (name, value) -> { }));
+
+ assertNotNull(ex.getCause());
+ assertEquals(ex.getCause().getClass(), ProtocolException.class);
+ }
+ }
+
+ @Test
+ public void corruptedHeaderBlockInteger() {
+ Decoder d = new Decoder(4096);
+ ByteBuffer data = ByteBuffer.wrap(new byte[]{
+ (byte) 0b11111111, // indexed
+ (byte) 0b10011010 // 25 + ...
+ });
+ UncheckedIOException e = assertVoidThrows(UncheckedIOException.class,
+ () -> d.decode(data, true, nopCallback()));
+ assertNotNull(e.getCause());
+ assertEquals(e.getCause().getClass(), ProtocolException.class);
+ assertExceptionMessageContains(e, "Unexpected end of header block");
+ }
+
+ // 5.1. Integer Representation
+ // ...
+ // Integer encodings that exceed implementation limits -- in value or octet
+ // length -- MUST be treated as decoding errors. Different limits can
+ // be set for each of the different uses of integers, based on
+ // implementation constraints.
+ @Test
+ public void headerBlockIntegerNoOverflow() {
+ Decoder d = new Decoder(4096);
+ ByteBuffer data = ByteBuffer.wrap(new byte[]{
+ (byte) 0b11111111, // indexed + 127
+ // Integer.MAX_VALUE - 127 (base 128, little-endian):
+ (byte) 0b10000000,
+ (byte) 0b11111111,
+ (byte) 0b11111111,
+ (byte) 0b11111111,
+ (byte) 0b00000111
+ });
+
+ IllegalArgumentException e = assertVoidThrows(IllegalArgumentException.class,
+ () -> d.decode(data, true, nopCallback()));
+
+ assertExceptionMessageContains(e, "index=2147483647");
+ }
+
+ @Test
+ public void headerBlockIntegerOverflow() {
+ Decoder d = new Decoder(4096);
+ ByteBuffer data = ByteBuffer.wrap(new byte[]{
+ (byte) 0b11111111, // indexed + 127
+ // Integer.MAX_VALUE - 127 + 1 (base 128, little endian):
+ (byte) 0b10000001,
+ (byte) 0b11111111,
+ (byte) 0b11111111,
+ (byte) 0b11111111,
+ (byte) 0b00000111
+ });
+
+ IllegalArgumentException e = assertVoidThrows(IllegalArgumentException.class,
+ () -> d.decode(data, true, nopCallback()));
+
+ assertExceptionMessageContains(e, "Integer overflow");
+ }
+
+ @Test
+ public void corruptedHeaderBlockString1() {
+ Decoder d = new Decoder(4096);
+ ByteBuffer data = ByteBuffer.wrap(new byte[]{
+ 0b00001111, // literal, index=15
+ 0b00000000,
+ 0b00001000, // huffman=false, length=8
+ 0b00000000, // \
+ 0b00000000, // but only 3 octets available...
+ 0b00000000 // /
+ });
+ UncheckedIOException e = assertVoidThrows(UncheckedIOException.class,
+ () -> d.decode(data, true, nopCallback()));
+ assertNotNull(e.getCause());
+ assertEquals(e.getCause().getClass(), ProtocolException.class);
+ assertExceptionMessageContains(e, "Unexpected end of header block");
+ }
+
+ @Test
+ public void corruptedHeaderBlockString2() {
+ Decoder d = new Decoder(4096);
+ ByteBuffer data = ByteBuffer.wrap(new byte[]{
+ 0b00001111, // literal, index=15
+ 0b00000000,
+ (byte) 0b10001000, // huffman=true, length=8
+ 0b00000000, // \
+ 0b00000000, // \
+ 0b00000000, // but only 5 octets available...
+ 0b00000000, // /
+ 0b00000000 // /
+ });
+ UncheckedIOException e = assertVoidThrows(UncheckedIOException.class,
+ () -> d.decode(data, true, nopCallback()));
+ assertNotNull(e.getCause());
+ assertEquals(e.getCause().getClass(), ProtocolException.class);
+ assertExceptionMessageContains(e, "Unexpected end of header block");
+ }
+
+ // 5.2. String Literal Representation
+ // ...A Huffman-encoded string literal containing the EOS symbol MUST be
+ // treated as a decoding error...
+ @Test
+ public void corruptedHeaderBlockHuffmanStringEOS() {
+ Decoder d = new Decoder(4096);
+ ByteBuffer data = ByteBuffer.wrap(new byte[]{
+ 0b00001111, // literal, index=15
+ 0b00000000,
+ (byte) 0b10000110, // huffman=true, length=6
+ 0b00011001, 0b01001101, (byte) 0b11111111,
+ (byte) 0b11111111, (byte) 0b11111111, (byte) 0b11111100
+ });
+ IllegalArgumentException e = assertVoidThrows(IllegalArgumentException.class,
+ () -> d.decode(data, true, nopCallback()));
+
+ assertExceptionMessageContains(e, "Encountered EOS");
+ }
+
+ // 5.2. String Literal Representation
+ // ...A padding strictly longer than 7 bits MUST be treated as a decoding
+ // error...
+ @Test
+ public void corruptedHeaderBlockHuffmanStringLongPadding1() {
+ Decoder d = new Decoder(4096);
+ ByteBuffer data = ByteBuffer.wrap(new byte[]{
+ 0b00001111, // literal, index=15
+ 0b00000000,
+ (byte) 0b10000011, // huffman=true, length=3
+ 0b00011001, 0b01001101, (byte) 0b11111111
+ // len("aei") + len(padding) = (5 + 5 + 5) + (9)
+ });
+ IllegalArgumentException e = assertVoidThrows(IllegalArgumentException.class,
+ () -> d.decode(data, true, nopCallback()));
+
+ assertExceptionMessageContains(e, "Padding is too long", "len=9");
+ }
+
+ @Test
+ public void corruptedHeaderBlockHuffmanStringLongPadding2() {
+ Decoder d = new Decoder(4096);
+ ByteBuffer data = ByteBuffer.wrap(new byte[]{
+ 0b00001111, // literal, index=15
+ 0b00000000,
+ (byte) 0b10000011, // huffman=true, length=3
+ 0b00011001, 0b01111010, (byte) 0b11111111
+ // len("aek") + len(padding) = (5 + 5 + 7) + (7)
+ });
+ assertVoidDoesNotThrow(() -> d.decode(data, true, nopCallback()));
+ }
+
+ // 5.2. String Literal Representation
+ // ...A padding not corresponding to the most significant bits of the code
+ // for the EOS symbol MUST be treated as a decoding error...
+ @Test
+ public void corruptedHeaderBlockHuffmanStringNotEOSPadding() {
+ Decoder d = new Decoder(4096);
+ ByteBuffer data = ByteBuffer.wrap(new byte[]{
+ 0b00001111, // literal, index=15
+ 0b00000000,
+ (byte) 0b10000011, // huffman=true, length=3
+ 0b00011001, 0b01111010, (byte) 0b11111110
+ });
+ IllegalArgumentException e = assertVoidThrows(IllegalArgumentException.class,
+ () -> d.decode(data, true, nopCallback()));
+
+ assertExceptionMessageContains(e, "Not a EOS prefix");
+ }
+
+ @Test
+ public void argsTestBiConsumerIsNull() {
+ Decoder decoder = new Decoder(4096);
+ assertVoidThrows(NullPointerException.class,
+ () -> decoder.decode(ByteBuffer.allocate(16), true, null));
+ }
+
+ @Test
+ public void argsTestByteBufferIsNull() {
+ Decoder decoder = new Decoder(4096);
+ assertVoidThrows(NullPointerException.class,
+ () -> decoder.decode(null, true, nopCallback()));
+ }
+
+ @Test
+ public void argsTestBothAreNull() {
+ Decoder decoder = new Decoder(4096);
+ assertVoidThrows(NullPointerException.class,
+ () -> decoder.decode(null, true, null));
+ }
+
+ private static void test(String hexdump,
+ String headerTable, String headerList) {
+ test(new Decoder(4096), hexdump, headerTable, headerList);
+ }
+
+ //
+ // Sometimes we need to keep the same decoder along several runs,
+ // as it models the same connection
+ //
+ private static void test(Decoder d, String hexdump,
+ String expectedHeaderTable, String expectedHeaderList) {
+
+ ByteBuffer source = SpecHelper.toBytes(hexdump);
+
+ List<String> actual = new LinkedList<>();
+ d.decode(source, true, (name, value) -> {
+ if (value == null) {
+ actual.add(name.toString());
+ } else {
+ actual.add(name + ": " + value);
+ }
+ });
+
+ assertEquals(d.getTable().getStateString(), expectedHeaderTable);
+ assertEquals(actual.stream().collect(Collectors.joining("\n")), expectedHeaderList);
+ }
+
+ private static DecodingCallback nopCallback() {
+ return (t, u) -> { };
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/EncoderTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,623 @@
+/*
+ * Copyright (c) 2014, 2016, 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.
+ */
+package sun.net.httpclient.hpack;
+
+import org.testng.annotations.Test;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Function;
+
+import static java.util.Arrays.asList;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static sun.net.httpclient.hpack.SpecHelper.toHexdump;
+import static sun.net.httpclient.hpack.TestHelper.assertVoidThrows;
+
+// TODO: map textual representation of commands from the spec to actual
+// calls to encoder (actually, this is a good idea for decoder as well)
+public final class EncoderTest {
+
+ //
+ // http://tools.ietf.org/html/rfc7541#appendix-C.2.1
+ //
+ @Test
+ public void example1() {
+
+ Encoder e = newCustomEncoder(256);
+ drainInitialUpdate(e);
+
+ e.literalWithIndexing("custom-key", false, "custom-header", false);
+ // @formatter:off
+ test(e,
+
+ "400a 6375 7374 6f6d 2d6b 6579 0d63 7573\n" +
+ "746f 6d2d 6865 6164 6572",
+
+ "[ 1] (s = 55) custom-key: custom-header\n" +
+ " Table size: 55");
+ // @formatter:on
+ }
+
+ //
+ // http://tools.ietf.org/html/rfc7541#appendix-C.2.2
+ //
+ @Test
+ public void example2() {
+
+ Encoder e = newCustomEncoder(256);
+ drainInitialUpdate(e);
+
+ e.literal(4, "/sample/path", false);
+ // @formatter:off
+ test(e,
+
+ "040c 2f73 616d 706c 652f 7061 7468",
+
+ "empty.");
+ // @formatter:on
+ }
+
+ //
+ // http://tools.ietf.org/html/rfc7541#appendix-C.2.3
+ //
+ @Test
+ public void example3() {
+
+ Encoder e = newCustomEncoder(256);
+ drainInitialUpdate(e);
+
+ e.literalNeverIndexed("password", false, "secret", false);
+ // @formatter:off
+ test(e,
+
+ "1008 7061 7373 776f 7264 0673 6563 7265\n" +
+ "74",
+
+ "empty.");
+ // @formatter:on
+ }
+
+ //
+ // http://tools.ietf.org/html/rfc7541#appendix-C.2.4
+ //
+ @Test
+ public void example4() {
+
+ Encoder e = newCustomEncoder(256);
+ drainInitialUpdate(e);
+
+ e.indexed(2);
+ // @formatter:off
+ test(e,
+
+ "82",
+
+ "empty.");
+ // @formatter:on
+ }
+
+ //
+ // http://tools.ietf.org/html/rfc7541#appendix-C.3
+ //
+ @Test
+ public void example5() {
+ Encoder e = newCustomEncoder(256);
+ drainInitialUpdate(e);
+
+ ByteBuffer output = ByteBuffer.allocate(64);
+ e.indexed(2);
+ e.encode(output);
+ e.indexed(6);
+ e.encode(output);
+ e.indexed(4);
+ e.encode(output);
+ e.literalWithIndexing(1, "www.example.com", false);
+ e.encode(output);
+
+ output.flip();
+
+ // @formatter:off
+ test(e, output,
+
+ "8286 8441 0f77 7777 2e65 7861 6d70 6c65\n" +
+ "2e63 6f6d",
+
+ "[ 1] (s = 57) :authority: www.example.com\n" +
+ " Table size: 57");
+
+ output.clear();
+
+ e.indexed( 2);
+ e.encode(output);
+ e.indexed( 6);
+ e.encode(output);
+ e.indexed( 4);
+ e.encode(output);
+ e.indexed(62);
+ e.encode(output);
+ e.literalWithIndexing(24, "no-cache", false);
+ e.encode(output);
+
+ output.flip();
+
+ test(e, output,
+
+ "8286 84be 5808 6e6f 2d63 6163 6865",
+
+ "[ 1] (s = 53) cache-control: no-cache\n" +
+ "[ 2] (s = 57) :authority: www.example.com\n" +
+ " Table size: 110");
+
+ output.clear();
+
+ e.indexed( 2);
+ e.encode(output);
+ e.indexed( 7);
+ e.encode(output);
+ e.indexed( 5);
+ e.encode(output);
+ e.indexed(63);
+ e.encode(output);
+ e.literalWithIndexing("custom-key", false, "custom-value", false);
+ e.encode(output);
+
+ output.flip();
+
+ test(e, output,
+
+ "8287 85bf 400a 6375 7374 6f6d 2d6b 6579\n" +
+ "0c63 7573 746f 6d2d 7661 6c75 65",
+
+ "[ 1] (s = 54) custom-key: custom-value\n" +
+ "[ 2] (s = 53) cache-control: no-cache\n" +
+ "[ 3] (s = 57) :authority: www.example.com\n" +
+ " Table size: 164");
+ // @formatter:on
+ }
+
+ //
+ // http://tools.ietf.org/html/rfc7541#appendix-C.4
+ //
+ @Test
+ public void example6() {
+ Encoder e = newCustomEncoder(256);
+ drainInitialUpdate(e);
+
+ ByteBuffer output = ByteBuffer.allocate(64);
+ e.indexed(2);
+ e.encode(output);
+ e.indexed(6);
+ e.encode(output);
+ e.indexed(4);
+ e.encode(output);
+ e.literalWithIndexing(1, "www.example.com", true);
+ e.encode(output);
+
+ output.flip();
+
+ // @formatter:off
+ test(e, output,
+
+ "8286 8441 8cf1 e3c2 e5f2 3a6b a0ab 90f4\n" +
+ "ff",
+
+ "[ 1] (s = 57) :authority: www.example.com\n" +
+ " Table size: 57");
+
+ output.clear();
+
+ e.indexed( 2);
+ e.encode(output);
+ e.indexed( 6);
+ e.encode(output);
+ e.indexed( 4);
+ e.encode(output);
+ e.indexed(62);
+ e.encode(output);
+ e.literalWithIndexing(24, "no-cache", true);
+ e.encode(output);
+
+ output.flip();
+
+ test(e, output,
+
+ "8286 84be 5886 a8eb 1064 9cbf",
+
+ "[ 1] (s = 53) cache-control: no-cache\n" +
+ "[ 2] (s = 57) :authority: www.example.com\n" +
+ " Table size: 110");
+
+ output.clear();
+
+ e.indexed( 2);
+ e.encode(output);
+ e.indexed( 7);
+ e.encode(output);
+ e.indexed( 5);
+ e.encode(output);
+ e.indexed(63);
+ e.encode(output);
+ e.literalWithIndexing("custom-key", true, "custom-value", true);
+ e.encode(output);
+
+ output.flip();
+
+ test(e, output,
+
+ "8287 85bf 4088 25a8 49e9 5ba9 7d7f 8925\n" +
+ "a849 e95b b8e8 b4bf",
+
+ "[ 1] (s = 54) custom-key: custom-value\n" +
+ "[ 2] (s = 53) cache-control: no-cache\n" +
+ "[ 3] (s = 57) :authority: www.example.com\n" +
+ " Table size: 164");
+ // @formatter:on
+ }
+
+ //
+ // http://tools.ietf.org/html/rfc7541#appendix-C.5
+ //
+ @Test
+ public void example7() {
+ Encoder e = newCustomEncoder(256);
+ drainInitialUpdate(e);
+
+ ByteBuffer output = ByteBuffer.allocate(128);
+ // @formatter:off
+ e.literalWithIndexing( 8, "302", false);
+ e.encode(output);
+ e.literalWithIndexing(24, "private", false);
+ e.encode(output);
+ e.literalWithIndexing(33, "Mon, 21 Oct 2013 20:13:21 GMT", false);
+ e.encode(output);
+ e.literalWithIndexing(46, "https://www.example.com", false);
+ e.encode(output);
+
+ output.flip();
+
+ test(e, output,
+
+ "4803 3330 3258 0770 7269 7661 7465 611d\n" +
+ "4d6f 6e2c 2032 3120 4f63 7420 3230 3133\n" +
+ "2032 303a 3133 3a32 3120 474d 546e 1768\n" +
+ "7474 7073 3a2f 2f77 7777 2e65 7861 6d70\n" +
+ "6c65 2e63 6f6d",
+
+ "[ 1] (s = 63) location: https://www.example.com\n" +
+ "[ 2] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT\n" +
+ "[ 3] (s = 52) cache-control: private\n" +
+ "[ 4] (s = 42) :status: 302\n" +
+ " Table size: 222");
+
+ output.clear();
+
+ e.literalWithIndexing( 8, "307", false);
+ e.encode(output);
+ e.indexed(65);
+ e.encode(output);
+ e.indexed(64);
+ e.encode(output);
+ e.indexed(63);
+ e.encode(output);
+
+ output.flip();
+
+ test(e, output,
+
+ "4803 3330 37c1 c0bf",
+
+ "[ 1] (s = 42) :status: 307\n" +
+ "[ 2] (s = 63) location: https://www.example.com\n" +
+ "[ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT\n" +
+ "[ 4] (s = 52) cache-control: private\n" +
+ " Table size: 222");
+
+ output.clear();
+
+ e.indexed( 8);
+ e.encode(output);
+ e.indexed(65);
+ e.encode(output);
+ e.literalWithIndexing(33, "Mon, 21 Oct 2013 20:13:22 GMT", false);
+ e.encode(output);
+ e.indexed(64);
+ e.encode(output);
+ e.literalWithIndexing(26, "gzip", false);
+ e.encode(output);
+ e.literalWithIndexing(55, "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", false);
+ e.encode(output);
+
+ output.flip();
+
+ test(e, output,
+
+ "88c1 611d 4d6f 6e2c 2032 3120 4f63 7420\n" +
+ "3230 3133 2032 303a 3133 3a32 3220 474d\n" +
+ "54c0 5a04 677a 6970 7738 666f 6f3d 4153\n" +
+ "444a 4b48 514b 425a 584f 5157 454f 5049\n" +
+ "5541 5851 5745 4f49 553b 206d 6178 2d61\n" +
+ "6765 3d33 3630 303b 2076 6572 7369 6f6e\n" +
+ "3d31",
+
+ "[ 1] (s = 98) set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1\n" +
+ "[ 2] (s = 52) content-encoding: gzip\n" +
+ "[ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:22 GMT\n" +
+ " Table size: 215");
+ // @formatter:on
+ }
+
+ //
+ // http://tools.ietf.org/html/rfc7541#appendix-C.6
+ //
+ @Test
+ public void example8() {
+ Encoder e = newCustomEncoder(256);
+ drainInitialUpdate(e);
+
+ ByteBuffer output = ByteBuffer.allocate(128);
+ // @formatter:off
+ e.literalWithIndexing( 8, "302", true);
+ e.encode(output);
+ e.literalWithIndexing(24, "private", true);
+ e.encode(output);
+ e.literalWithIndexing(33, "Mon, 21 Oct 2013 20:13:21 GMT", true);
+ e.encode(output);
+ e.literalWithIndexing(46, "https://www.example.com", true);
+ e.encode(output);
+
+ output.flip();
+
+ test(e, output,
+
+ "4882 6402 5885 aec3 771a 4b61 96d0 7abe\n" +
+ "9410 54d4 44a8 2005 9504 0b81 66e0 82a6\n" +
+ "2d1b ff6e 919d 29ad 1718 63c7 8f0b 97c8\n" +
+ "e9ae 82ae 43d3",
+
+ "[ 1] (s = 63) location: https://www.example.com\n" +
+ "[ 2] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT\n" +
+ "[ 3] (s = 52) cache-control: private\n" +
+ "[ 4] (s = 42) :status: 302\n" +
+ " Table size: 222");
+
+ output.clear();
+
+ e.literalWithIndexing( 8, "307", true);
+ e.encode(output);
+ e.indexed(65);
+ e.encode(output);
+ e.indexed(64);
+ e.encode(output);
+ e.indexed(63);
+ e.encode(output);
+
+ output.flip();
+
+ test(e, output,
+
+ "4883 640e ffc1 c0bf",
+
+ "[ 1] (s = 42) :status: 307\n" +
+ "[ 2] (s = 63) location: https://www.example.com\n" +
+ "[ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT\n" +
+ "[ 4] (s = 52) cache-control: private\n" +
+ " Table size: 222");
+
+ output.clear();
+
+ e.indexed( 8);
+ e.encode(output);
+ e.indexed(65);
+ e.encode(output);
+ e.literalWithIndexing(33, "Mon, 21 Oct 2013 20:13:22 GMT", true);
+ e.encode(output);
+ e.indexed(64);
+ e.encode(output);
+ e.literalWithIndexing(26, "gzip", true);
+ e.encode(output);
+ e.literalWithIndexing(55, "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", true);
+ e.encode(output);
+
+ output.flip();
+
+ test(e, output,
+
+ "88c1 6196 d07a be94 1054 d444 a820 0595\n" +
+ "040b 8166 e084 a62d 1bff c05a 839b d9ab\n" +
+ "77ad 94e7 821d d7f2 e6c7 b335 dfdf cd5b\n" +
+ "3960 d5af 2708 7f36 72c1 ab27 0fb5 291f\n" +
+ "9587 3160 65c0 03ed 4ee5 b106 3d50 07",
+
+ "[ 1] (s = 98) set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1\n" +
+ "[ 2] (s = 52) content-encoding: gzip\n" +
+ "[ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:22 GMT\n" +
+ " Table size: 215");
+ // @formatter:on
+ }
+
+ @Test
+ public void initialSizeUpdateDefaultEncoder() {
+ Function<Integer, Encoder> e = Encoder::new;
+ testSizeUpdate(e, 1024, asList(), asList(0));
+ testSizeUpdate(e, 1024, asList(1024), asList(0));
+ testSizeUpdate(e, 1024, asList(1024, 1024), asList(0));
+ testSizeUpdate(e, 1024, asList(1024, 512), asList(0));
+ testSizeUpdate(e, 1024, asList(512, 1024), asList(0));
+ testSizeUpdate(e, 1024, asList(512, 2048), asList(0));
+ }
+
+ @Test
+ public void initialSizeUpdateCustomEncoder() {
+ Function<Integer, Encoder> e = EncoderTest::newCustomEncoder;
+ testSizeUpdate(e, 1024, asList(), asList(1024));
+ testSizeUpdate(e, 1024, asList(1024), asList(1024));
+ testSizeUpdate(e, 1024, asList(1024, 1024), asList(1024));
+ testSizeUpdate(e, 1024, asList(1024, 512), asList(512));
+ testSizeUpdate(e, 1024, asList(512, 1024), asList(1024));
+ testSizeUpdate(e, 1024, asList(512, 2048), asList(2048));
+ }
+
+ @Test
+ public void seriesOfSizeUpdatesDefaultEncoder() {
+ Function<Integer, Encoder> e = c -> {
+ Encoder encoder = new Encoder(c);
+ drainInitialUpdate(encoder);
+ return encoder;
+ };
+ testSizeUpdate(e, 0, asList(0), asList());
+ testSizeUpdate(e, 1024, asList(1024), asList());
+ testSizeUpdate(e, 1024, asList(2048), asList());
+ testSizeUpdate(e, 1024, asList(512), asList());
+ testSizeUpdate(e, 1024, asList(1024, 1024), asList());
+ testSizeUpdate(e, 1024, asList(1024, 2048), asList());
+ testSizeUpdate(e, 1024, asList(2048, 1024), asList());
+ testSizeUpdate(e, 1024, asList(1024, 512), asList());
+ testSizeUpdate(e, 1024, asList(512, 1024), asList());
+ }
+
+ //
+ // https://tools.ietf.org/html/rfc7541#section-4.2
+ //
+ @Test
+ public void seriesOfSizeUpdatesCustomEncoder() {
+ Function<Integer, Encoder> e = c -> {
+ Encoder encoder = newCustomEncoder(c);
+ drainInitialUpdate(encoder);
+ return encoder;
+ };
+ testSizeUpdate(e, 0, asList(0), asList());
+ testSizeUpdate(e, 1024, asList(1024), asList());
+ testSizeUpdate(e, 1024, asList(2048), asList(2048));
+ testSizeUpdate(e, 1024, asList(512), asList(512));
+ testSizeUpdate(e, 1024, asList(1024, 1024), asList());
+ testSizeUpdate(e, 1024, asList(1024, 2048), asList(2048));
+ testSizeUpdate(e, 1024, asList(2048, 1024), asList());
+ testSizeUpdate(e, 1024, asList(1024, 512), asList(512));
+ testSizeUpdate(e, 1024, asList(512, 1024), asList(512, 1024));
+ }
+
+ @Test
+ public void callSequenceViolations() {
+ { // Hasn't set up a header
+ Encoder e = new Encoder(0);
+ assertVoidThrows(IllegalStateException.class, () -> e.encode(ByteBuffer.allocate(16)));
+ }
+ { // Can't set up header while there's an unfinished encoding
+ Encoder e = new Encoder(0);
+ e.indexed(32);
+ assertVoidThrows(IllegalStateException.class, () -> e.indexed(32));
+ }
+ { // Can't setMaxCapacity while there's an unfinished encoding
+ Encoder e = new Encoder(0);
+ e.indexed(32);
+ assertVoidThrows(IllegalStateException.class, () -> e.setMaxCapacity(512));
+ }
+ { // Hasn't set up a header
+ Encoder e = new Encoder(0);
+ e.setMaxCapacity(256);
+ assertVoidThrows(IllegalStateException.class, () -> e.encode(ByteBuffer.allocate(16)));
+ }
+ { // Hasn't set up a header after the previous encoding
+ Encoder e = new Encoder(0);
+ e.indexed(0);
+ boolean encoded = e.encode(ByteBuffer.allocate(16));
+ assertTrue(encoded); // assumption
+ assertVoidThrows(IllegalStateException.class, () -> e.encode(ByteBuffer.allocate(16)));
+ }
+ }
+
+ private static void test(Encoder encoder,
+ String expectedTableState,
+ String expectedHexdump) {
+
+ ByteBuffer b = ByteBuffer.allocate(128);
+ encoder.encode(b);
+ b.flip();
+ test(encoder, b, expectedTableState, expectedHexdump);
+ }
+
+ private static void test(Encoder encoder,
+ ByteBuffer output,
+ String expectedHexdump,
+ String expectedTableState) {
+
+ String actualTableState = encoder.getHeaderTable().getStateString();
+ assertEquals(actualTableState, expectedTableState);
+
+ String actualHexdump = toHexdump(output);
+ assertEquals(actualHexdump, expectedHexdump.replaceAll("\\n", " "));
+ }
+
+ // initial size - the size encoder is constructed with
+ // updates - a sequence of values for consecutive calls to encoder.setMaxCapacity
+ // expected - a sequence of values expected to be decoded by a decoder
+ private void testSizeUpdate(Function<Integer, Encoder> encoder,
+ int initialSize,
+ List<Integer> updates,
+ List<Integer> expected) {
+ Encoder e = encoder.apply(initialSize);
+ updates.forEach(e::setMaxCapacity);
+ ByteBuffer b = ByteBuffer.allocate(64);
+ e.header("a", "b");
+ e.encode(b);
+ b.flip();
+ Decoder d = new Decoder(updates.isEmpty() ? initialSize : Collections.max(updates));
+ List<Integer> actual = new ArrayList<>();
+ d.decode(b, true, new DecodingCallback() {
+ @Override
+ public void onDecoded(CharSequence name, CharSequence value) { }
+
+ @Override
+ public void onSizeUpdate(int capacity) {
+ actual.add(capacity);
+ }
+ });
+ assertEquals(actual, expected);
+ }
+
+ //
+ // Default encoder does not need any table, therefore a subclass that
+ // behaves differently is needed
+ //
+ private static Encoder newCustomEncoder(int maxCapacity) {
+ return new Encoder(maxCapacity) {
+ @Override
+ protected int calculateCapacity(int maxCapacity) {
+ return maxCapacity;
+ }
+ };
+ }
+
+ private static void drainInitialUpdate(Encoder e) {
+ ByteBuffer b = ByteBuffer.allocate(4);
+ e.header("a", "b");
+ boolean done;
+ do {
+ done = e.encode(b);
+ b.flip();
+ } while (!done);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/HeaderTableTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,375 @@
+/*
+ * Copyright (c) 2014, 2016, 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.
+ */
+package sun.net.httpclient.hpack;
+
+import org.testng.annotations.Test;
+import sun.net.httpclient.hpack.HeaderTable.HeaderField;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static java.lang.String.format;
+import static org.testng.Assert.assertEquals;
+import static sun.net.httpclient.hpack.TestHelper.*;
+
+public class HeaderTableTest {
+
+ //
+ // https://tools.ietf.org/html/rfc7541#appendix-A
+ //
+ // @formatter:off
+ private static final String SPEC =
+ " | 1 | :authority | |\n" +
+ " | 2 | :method | GET |\n" +
+ " | 3 | :method | POST |\n" +
+ " | 4 | :path | / |\n" +
+ " | 5 | :path | /index.html |\n" +
+ " | 6 | :scheme | http |\n" +
+ " | 7 | :scheme | https |\n" +
+ " | 8 | :status | 200 |\n" +
+ " | 9 | :status | 204 |\n" +
+ " | 10 | :status | 206 |\n" +
+ " | 11 | :status | 304 |\n" +
+ " | 12 | :status | 400 |\n" +
+ " | 13 | :status | 404 |\n" +
+ " | 14 | :status | 500 |\n" +
+ " | 15 | accept-charset | |\n" +
+ " | 16 | accept-encoding | gzip, deflate |\n" +
+ " | 17 | accept-language | |\n" +
+ " | 18 | accept-ranges | |\n" +
+ " | 19 | accept | |\n" +
+ " | 20 | access-control-allow-origin | |\n" +
+ " | 21 | age | |\n" +
+ " | 22 | allow | |\n" +
+ " | 23 | authorization | |\n" +
+ " | 24 | cache-control | |\n" +
+ " | 25 | content-disposition | |\n" +
+ " | 26 | content-encoding | |\n" +
+ " | 27 | content-language | |\n" +
+ " | 28 | content-length | |\n" +
+ " | 29 | content-location | |\n" +
+ " | 30 | content-range | |\n" +
+ " | 31 | content-type | |\n" +
+ " | 32 | cookie | |\n" +
+ " | 33 | date | |\n" +
+ " | 34 | etag | |\n" +
+ " | 35 | expect | |\n" +
+ " | 36 | expires | |\n" +
+ " | 37 | from | |\n" +
+ " | 38 | host | |\n" +
+ " | 39 | if-match | |\n" +
+ " | 40 | if-modified-since | |\n" +
+ " | 41 | if-none-match | |\n" +
+ " | 42 | if-range | |\n" +
+ " | 43 | if-unmodified-since | |\n" +
+ " | 44 | last-modified | |\n" +
+ " | 45 | link | |\n" +
+ " | 46 | location | |\n" +
+ " | 47 | max-forwards | |\n" +
+ " | 48 | proxy-authenticate | |\n" +
+ " | 49 | proxy-authorization | |\n" +
+ " | 50 | range | |\n" +
+ " | 51 | referer | |\n" +
+ " | 52 | refresh | |\n" +
+ " | 53 | retry-after | |\n" +
+ " | 54 | server | |\n" +
+ " | 55 | set-cookie | |\n" +
+ " | 56 | strict-transport-security | |\n" +
+ " | 57 | transfer-encoding | |\n" +
+ " | 58 | user-agent | |\n" +
+ " | 59 | vary | |\n" +
+ " | 60 | via | |\n" +
+ " | 61 | www-authenticate | |\n";
+ // @formatter:on
+
+ private static final int STATIC_TABLE_LENGTH = createStaticEntries().size();
+ private final Random rnd = newRandom();
+
+ @Test
+ public void staticData() {
+ HeaderTable table = new HeaderTable(0);
+ Map<Integer, HeaderField> staticHeaderFields = createStaticEntries();
+
+ Map<String, Integer> minimalIndexes = new HashMap<>();
+
+ for (Map.Entry<Integer, HeaderField> e : staticHeaderFields.entrySet()) {
+ Integer idx = e.getKey();
+ String hName = e.getValue().name;
+ Integer midx = minimalIndexes.get(hName);
+ if (midx == null) {
+ minimalIndexes.put(hName, idx);
+ } else {
+ minimalIndexes.put(hName, Math.min(idx, midx));
+ }
+ }
+
+ staticHeaderFields.entrySet().forEach(
+ e -> {
+ // lookup
+ HeaderField actualHeaderField = table.get(e.getKey());
+ HeaderField expectedHeaderField = e.getValue();
+ assertEquals(actualHeaderField, expectedHeaderField);
+
+ // reverse lookup (name, value)
+ String hName = expectedHeaderField.name;
+ String hValue = expectedHeaderField.value;
+ int expectedIndex = e.getKey();
+ int actualIndex = table.indexOf(hName, hValue);
+
+ assertEquals(actualIndex, expectedIndex);
+
+ // reverse lookup (name)
+ int expectedMinimalIndex = minimalIndexes.get(hName);
+ int actualMinimalIndex = table.indexOf(hName, "blah-blah");
+
+ assertEquals(-actualMinimalIndex, expectedMinimalIndex);
+ }
+ );
+ }
+
+ @Test
+ public void constructorSetsMaxSize() {
+ int size = rnd.nextInt(64);
+ HeaderTable t = new HeaderTable(size);
+ assertEquals(t.size(), 0);
+ assertEquals(t.maxSize(), size);
+ }
+
+ @Test
+ public void negativeMaximumSize() {
+ int maxSize = -(rnd.nextInt(100) + 1); // [-100, -1]
+ IllegalArgumentException e =
+ assertVoidThrows(IllegalArgumentException.class,
+ () -> new HeaderTable(0).setMaxSize(maxSize));
+ assertExceptionMessageContains(e, "maxSize");
+ }
+
+ @Test
+ public void zeroMaximumSize() {
+ HeaderTable table = new HeaderTable(0);
+ table.setMaxSize(0);
+ assertEquals(table.maxSize(), 0);
+ }
+
+ @Test
+ public void negativeIndex() {
+ int idx = -(rnd.nextInt(256) + 1); // [-256, -1]
+ IllegalArgumentException e =
+ assertVoidThrows(IllegalArgumentException.class,
+ () -> new HeaderTable(0).get(idx));
+ assertExceptionMessageContains(e, "index");
+ }
+
+ @Test
+ public void zeroIndex() {
+ IllegalArgumentException e =
+ assertThrows(IllegalArgumentException.class,
+ () -> new HeaderTable(0).get(0));
+ assertExceptionMessageContains(e, "index");
+ }
+
+ @Test
+ public void length() {
+ HeaderTable table = new HeaderTable(0);
+ assertEquals(table.length(), STATIC_TABLE_LENGTH);
+ }
+
+ @Test
+ public void indexOutsideStaticRange() {
+ HeaderTable table = new HeaderTable(0);
+ int idx = table.length() + (rnd.nextInt(256) + 1);
+ IllegalArgumentException e =
+ assertThrows(IllegalArgumentException.class,
+ () -> table.get(idx));
+ assertExceptionMessageContains(e, "index");
+ }
+
+ @Test
+ public void entryPutAfterStaticArea() {
+ HeaderTable table = new HeaderTable(256);
+ int idx = table.length() + 1;
+ assertThrows(IllegalArgumentException.class, () -> table.get(idx));
+
+ byte[] bytes = new byte[32];
+ rnd.nextBytes(bytes);
+ String name = new String(bytes, StandardCharsets.ISO_8859_1);
+ String value = "custom-value";
+
+ table.put(name, value);
+ HeaderField f = table.get(idx);
+ assertEquals(name, f.name);
+ assertEquals(value, f.value);
+ }
+
+ @Test
+ public void staticTableHasZeroSize() {
+ HeaderTable table = new HeaderTable(0);
+ assertEquals(0, table.size());
+ }
+
+ @Test
+ public void lowerIndexPriority() {
+ HeaderTable table = new HeaderTable(256);
+ int oldLength = table.length();
+ table.put("bender", "rodriguez");
+ table.put("bender", "rodriguez");
+ table.put("bender", "rodriguez");
+
+ assertEquals(table.length(), oldLength + 3); // more like an assumption
+ int i = table.indexOf("bender", "rodriguez");
+ assertEquals(oldLength + 1, i);
+ }
+
+ @Test
+ public void lowerIndexPriority2() {
+ HeaderTable table = new HeaderTable(256);
+ int oldLength = table.length();
+ int idx = rnd.nextInt(oldLength) + 1;
+ HeaderField f = table.get(idx);
+ table.put(f.name, f.value);
+ assertEquals(table.length(), oldLength + 1);
+ int i = table.indexOf(f.name, f.value);
+ assertEquals(idx, i);
+ }
+
+ // TODO: negative indexes check
+ // TODO: ensure full table clearance when adding huge header field
+ // TODO: ensure eviction deletes minimum needed entries, not more
+
+ @Test
+ public void fifo() {
+ HeaderTable t = new HeaderTable(Integer.MAX_VALUE);
+ // Let's add a series of header fields
+ int NUM_HEADERS = 32;
+ for (int i = 1; i <= NUM_HEADERS; i++) {
+ String s = String.valueOf(i);
+ t.put(s, s);
+ }
+ // They MUST appear in a FIFO order:
+ // newer entries are at lower indexes
+ // older entries are at higher indexes
+ for (int j = 1; j <= NUM_HEADERS; j++) {
+ HeaderField f = t.get(STATIC_TABLE_LENGTH + j);
+ int actualName = Integer.parseInt(f.name);
+ int expectedName = NUM_HEADERS - j + 1;
+ assertEquals(expectedName, actualName);
+ }
+ // Entries MUST be evicted in the order they were added:
+ // the newer the entry the later it is evicted
+ for (int k = 1; k <= NUM_HEADERS; k++) {
+ HeaderField f = t.evictEntry();
+ assertEquals(String.valueOf(k), f.name);
+ }
+ }
+
+ @Test
+ public void indexOf() {
+ HeaderTable t = new HeaderTable(Integer.MAX_VALUE);
+ // Let's put a series of header fields
+ int NUM_HEADERS = 32;
+ for (int i = 1; i <= NUM_HEADERS; i++) {
+ String s = String.valueOf(i);
+ t.put(s, s);
+ }
+ // and verify indexOf (reverse lookup) returns correct indexes for
+ // full lookup
+ for (int j = 1; j <= NUM_HEADERS; j++) {
+ String s = String.valueOf(j);
+ int actualIndex = t.indexOf(s, s);
+ int expectedIndex = STATIC_TABLE_LENGTH + NUM_HEADERS - j + 1;
+ assertEquals(expectedIndex, actualIndex);
+ }
+ // as well as for just a name lookup
+ for (int j = 1; j <= NUM_HEADERS; j++) {
+ String s = String.valueOf(j);
+ int actualIndex = t.indexOf(s, "blah");
+ int expectedIndex = -(STATIC_TABLE_LENGTH + NUM_HEADERS - j + 1);
+ assertEquals(expectedIndex, actualIndex);
+ }
+ // lookup for non-existent name returns 0
+ assertEquals(0, t.indexOf("chupacabra", "1"));
+ }
+
+ @Test
+ public void testToString() {
+ HeaderTable table = new HeaderTable(0);
+ {
+ table.setMaxSize(2048);
+ assertEquals("entries: 0; used 0/2048 (0.0%)", table.toString());
+ }
+
+ {
+ String name = "custom-name";
+ String value = "custom-value";
+ int size = 512;
+
+ table.setMaxSize(size);
+ table.put(name, value);
+ String s = table.toString();
+
+ int used = name.length() + value.length() + 32;
+ double ratio = used * 100.0 / size;
+
+ String expected = format("entries: 1; used %s/%s (%.1f%%)", used, size, ratio);
+ assertEquals(expected, s);
+ }
+
+ {
+ table.setMaxSize(78);
+ table.put(":method", "");
+ table.put(":status", "");
+ String s = table.toString();
+ assertEquals("entries: 2; used 78/78 (100.0%)", s);
+ }
+ }
+
+ @Test
+ public void stateString() {
+ HeaderTable table = new HeaderTable(256);
+ table.put("custom-key", "custom-header");
+ // @formatter:off
+ assertEquals("[ 1] (s = 55) custom-key: custom-header\n" +
+ " Table size: 55", table.getStateString());
+ // @formatter:on
+ }
+
+ private static Map<Integer, HeaderField> createStaticEntries() {
+ Pattern line = Pattern.compile(
+ "\\|\\s*(?<index>\\d+?)\\s*\\|\\s*(?<name>.+?)\\s*\\|\\s*(?<value>.*?)\\s*\\|");
+ Matcher m = line.matcher(SPEC);
+ Map<Integer, HeaderField> result = new HashMap<>();
+ while (m.find()) {
+ int index = Integer.parseInt(m.group("index"));
+ String name = m.group("name");
+ String value = m.group("value");
+ HeaderField f = new HeaderField(name, value);
+ result.put(index, f);
+ }
+ return Collections.unmodifiableMap(result); // lol
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/HuffmanTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,623 @@
+/*
+ * Copyright (c) 2015, 2016, 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.
+ */
+package sun.net.httpclient.hpack;
+
+import org.testng.annotations.Test;
+
+import java.nio.ByteBuffer;
+import java.util.Stack;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static java.lang.Integer.parseInt;
+import static org.testng.Assert.*;
+
+public final class HuffmanTest {
+
+ //
+ // https://tools.ietf.org/html/rfc7541#appendix-B
+ //
+ private static final String SPEC =
+ // @formatter:off
+ " code as bits as hex len\n" +
+ " sym aligned to MSB aligned in\n" +
+ " to LSB bits\n" +
+ " ( 0) |11111111|11000 1ff8 [13]\n" +
+ " ( 1) |11111111|11111111|1011000 7fffd8 [23]\n" +
+ " ( 2) |11111111|11111111|11111110|0010 fffffe2 [28]\n" +
+ " ( 3) |11111111|11111111|11111110|0011 fffffe3 [28]\n" +
+ " ( 4) |11111111|11111111|11111110|0100 fffffe4 [28]\n" +
+ " ( 5) |11111111|11111111|11111110|0101 fffffe5 [28]\n" +
+ " ( 6) |11111111|11111111|11111110|0110 fffffe6 [28]\n" +
+ " ( 7) |11111111|11111111|11111110|0111 fffffe7 [28]\n" +
+ " ( 8) |11111111|11111111|11111110|1000 fffffe8 [28]\n" +
+ " ( 9) |11111111|11111111|11101010 ffffea [24]\n" +
+ " ( 10) |11111111|11111111|11111111|111100 3ffffffc [30]\n" +
+ " ( 11) |11111111|11111111|11111110|1001 fffffe9 [28]\n" +
+ " ( 12) |11111111|11111111|11111110|1010 fffffea [28]\n" +
+ " ( 13) |11111111|11111111|11111111|111101 3ffffffd [30]\n" +
+ " ( 14) |11111111|11111111|11111110|1011 fffffeb [28]\n" +
+ " ( 15) |11111111|11111111|11111110|1100 fffffec [28]\n" +
+ " ( 16) |11111111|11111111|11111110|1101 fffffed [28]\n" +
+ " ( 17) |11111111|11111111|11111110|1110 fffffee [28]\n" +
+ " ( 18) |11111111|11111111|11111110|1111 fffffef [28]\n" +
+ " ( 19) |11111111|11111111|11111111|0000 ffffff0 [28]\n" +
+ " ( 20) |11111111|11111111|11111111|0001 ffffff1 [28]\n" +
+ " ( 21) |11111111|11111111|11111111|0010 ffffff2 [28]\n" +
+ " ( 22) |11111111|11111111|11111111|111110 3ffffffe [30]\n" +
+ " ( 23) |11111111|11111111|11111111|0011 ffffff3 [28]\n" +
+ " ( 24) |11111111|11111111|11111111|0100 ffffff4 [28]\n" +
+ " ( 25) |11111111|11111111|11111111|0101 ffffff5 [28]\n" +
+ " ( 26) |11111111|11111111|11111111|0110 ffffff6 [28]\n" +
+ " ( 27) |11111111|11111111|11111111|0111 ffffff7 [28]\n" +
+ " ( 28) |11111111|11111111|11111111|1000 ffffff8 [28]\n" +
+ " ( 29) |11111111|11111111|11111111|1001 ffffff9 [28]\n" +
+ " ( 30) |11111111|11111111|11111111|1010 ffffffa [28]\n" +
+ " ( 31) |11111111|11111111|11111111|1011 ffffffb [28]\n" +
+ " ' ' ( 32) |010100 14 [ 6]\n" +
+ " '!' ( 33) |11111110|00 3f8 [10]\n" +
+ " '\"' ( 34) |11111110|01 3f9 [10]\n" +
+ " '#' ( 35) |11111111|1010 ffa [12]\n" +
+ " '$' ( 36) |11111111|11001 1ff9 [13]\n" +
+ " '%' ( 37) |010101 15 [ 6]\n" +
+ " '&' ( 38) |11111000 f8 [ 8]\n" +
+ " ''' ( 39) |11111111|010 7fa [11]\n" +
+ " '(' ( 40) |11111110|10 3fa [10]\n" +
+ " ')' ( 41) |11111110|11 3fb [10]\n" +
+ " '*' ( 42) |11111001 f9 [ 8]\n" +
+ " '+' ( 43) |11111111|011 7fb [11]\n" +
+ " ',' ( 44) |11111010 fa [ 8]\n" +
+ " '-' ( 45) |010110 16 [ 6]\n" +
+ " '.' ( 46) |010111 17 [ 6]\n" +
+ " '/' ( 47) |011000 18 [ 6]\n" +
+ " '0' ( 48) |00000 0 [ 5]\n" +
+ " '1' ( 49) |00001 1 [ 5]\n" +
+ " '2' ( 50) |00010 2 [ 5]\n" +
+ " '3' ( 51) |011001 19 [ 6]\n" +
+ " '4' ( 52) |011010 1a [ 6]\n" +
+ " '5' ( 53) |011011 1b [ 6]\n" +
+ " '6' ( 54) |011100 1c [ 6]\n" +
+ " '7' ( 55) |011101 1d [ 6]\n" +
+ " '8' ( 56) |011110 1e [ 6]\n" +
+ " '9' ( 57) |011111 1f [ 6]\n" +
+ " ':' ( 58) |1011100 5c [ 7]\n" +
+ " ';' ( 59) |11111011 fb [ 8]\n" +
+ " '<' ( 60) |11111111|1111100 7ffc [15]\n" +
+ " '=' ( 61) |100000 20 [ 6]\n" +
+ " '>' ( 62) |11111111|1011 ffb [12]\n" +
+ " '?' ( 63) |11111111|00 3fc [10]\n" +
+ " '@' ( 64) |11111111|11010 1ffa [13]\n" +
+ " 'A' ( 65) |100001 21 [ 6]\n" +
+ " 'B' ( 66) |1011101 5d [ 7]\n" +
+ " 'C' ( 67) |1011110 5e [ 7]\n" +
+ " 'D' ( 68) |1011111 5f [ 7]\n" +
+ " 'E' ( 69) |1100000 60 [ 7]\n" +
+ " 'F' ( 70) |1100001 61 [ 7]\n" +
+ " 'G' ( 71) |1100010 62 [ 7]\n" +
+ " 'H' ( 72) |1100011 63 [ 7]\n" +
+ " 'I' ( 73) |1100100 64 [ 7]\n" +
+ " 'J' ( 74) |1100101 65 [ 7]\n" +
+ " 'K' ( 75) |1100110 66 [ 7]\n" +
+ " 'L' ( 76) |1100111 67 [ 7]\n" +
+ " 'M' ( 77) |1101000 68 [ 7]\n" +
+ " 'N' ( 78) |1101001 69 [ 7]\n" +
+ " 'O' ( 79) |1101010 6a [ 7]\n" +
+ " 'P' ( 80) |1101011 6b [ 7]\n" +
+ " 'Q' ( 81) |1101100 6c [ 7]\n" +
+ " 'R' ( 82) |1101101 6d [ 7]\n" +
+ " 'S' ( 83) |1101110 6e [ 7]\n" +
+ " 'T' ( 84) |1101111 6f [ 7]\n" +
+ " 'U' ( 85) |1110000 70 [ 7]\n" +
+ " 'V' ( 86) |1110001 71 [ 7]\n" +
+ " 'W' ( 87) |1110010 72 [ 7]\n" +
+ " 'X' ( 88) |11111100 fc [ 8]\n" +
+ " 'Y' ( 89) |1110011 73 [ 7]\n" +
+ " 'Z' ( 90) |11111101 fd [ 8]\n" +
+ " '[' ( 91) |11111111|11011 1ffb [13]\n" +
+ " '\\' ( 92) |11111111|11111110|000 7fff0 [19]\n" +
+ " ']' ( 93) |11111111|11100 1ffc [13]\n" +
+ " '^' ( 94) |11111111|111100 3ffc [14]\n" +
+ " '_' ( 95) |100010 22 [ 6]\n" +
+ " '`' ( 96) |11111111|1111101 7ffd [15]\n" +
+ " 'a' ( 97) |00011 3 [ 5]\n" +
+ " 'b' ( 98) |100011 23 [ 6]\n" +
+ " 'c' ( 99) |00100 4 [ 5]\n" +
+ " 'd' (100) |100100 24 [ 6]\n" +
+ " 'e' (101) |00101 5 [ 5]\n" +
+ " 'f' (102) |100101 25 [ 6]\n" +
+ " 'g' (103) |100110 26 [ 6]\n" +
+ " 'h' (104) |100111 27 [ 6]\n" +
+ " 'i' (105) |00110 6 [ 5]\n" +
+ " 'j' (106) |1110100 74 [ 7]\n" +
+ " 'k' (107) |1110101 75 [ 7]\n" +
+ " 'l' (108) |101000 28 [ 6]\n" +
+ " 'm' (109) |101001 29 [ 6]\n" +
+ " 'n' (110) |101010 2a [ 6]\n" +
+ " 'o' (111) |00111 7 [ 5]\n" +
+ " 'p' (112) |101011 2b [ 6]\n" +
+ " 'q' (113) |1110110 76 [ 7]\n" +
+ " 'r' (114) |101100 2c [ 6]\n" +
+ " 's' (115) |01000 8 [ 5]\n" +
+ " 't' (116) |01001 9 [ 5]\n" +
+ " 'u' (117) |101101 2d [ 6]\n" +
+ " 'v' (118) |1110111 77 [ 7]\n" +
+ " 'w' (119) |1111000 78 [ 7]\n" +
+ " 'x' (120) |1111001 79 [ 7]\n" +
+ " 'y' (121) |1111010 7a [ 7]\n" +
+ " 'z' (122) |1111011 7b [ 7]\n" +
+ " '{' (123) |11111111|1111110 7ffe [15]\n" +
+ " '|' (124) |11111111|100 7fc [11]\n" +
+ " '}' (125) |11111111|111101 3ffd [14]\n" +
+ " '~' (126) |11111111|11101 1ffd [13]\n" +
+ " (127) |11111111|11111111|11111111|1100 ffffffc [28]\n" +
+ " (128) |11111111|11111110|0110 fffe6 [20]\n" +
+ " (129) |11111111|11111111|010010 3fffd2 [22]\n" +
+ " (130) |11111111|11111110|0111 fffe7 [20]\n" +
+ " (131) |11111111|11111110|1000 fffe8 [20]\n" +
+ " (132) |11111111|11111111|010011 3fffd3 [22]\n" +
+ " (133) |11111111|11111111|010100 3fffd4 [22]\n" +
+ " (134) |11111111|11111111|010101 3fffd5 [22]\n" +
+ " (135) |11111111|11111111|1011001 7fffd9 [23]\n" +
+ " (136) |11111111|11111111|010110 3fffd6 [22]\n" +
+ " (137) |11111111|11111111|1011010 7fffda [23]\n" +
+ " (138) |11111111|11111111|1011011 7fffdb [23]\n" +
+ " (139) |11111111|11111111|1011100 7fffdc [23]\n" +
+ " (140) |11111111|11111111|1011101 7fffdd [23]\n" +
+ " (141) |11111111|11111111|1011110 7fffde [23]\n" +
+ " (142) |11111111|11111111|11101011 ffffeb [24]\n" +
+ " (143) |11111111|11111111|1011111 7fffdf [23]\n" +
+ " (144) |11111111|11111111|11101100 ffffec [24]\n" +
+ " (145) |11111111|11111111|11101101 ffffed [24]\n" +
+ " (146) |11111111|11111111|010111 3fffd7 [22]\n" +
+ " (147) |11111111|11111111|1100000 7fffe0 [23]\n" +
+ " (148) |11111111|11111111|11101110 ffffee [24]\n" +
+ " (149) |11111111|11111111|1100001 7fffe1 [23]\n" +
+ " (150) |11111111|11111111|1100010 7fffe2 [23]\n" +
+ " (151) |11111111|11111111|1100011 7fffe3 [23]\n" +
+ " (152) |11111111|11111111|1100100 7fffe4 [23]\n" +
+ " (153) |11111111|11111110|11100 1fffdc [21]\n" +
+ " (154) |11111111|11111111|011000 3fffd8 [22]\n" +
+ " (155) |11111111|11111111|1100101 7fffe5 [23]\n" +
+ " (156) |11111111|11111111|011001 3fffd9 [22]\n" +
+ " (157) |11111111|11111111|1100110 7fffe6 [23]\n" +
+ " (158) |11111111|11111111|1100111 7fffe7 [23]\n" +
+ " (159) |11111111|11111111|11101111 ffffef [24]\n" +
+ " (160) |11111111|11111111|011010 3fffda [22]\n" +
+ " (161) |11111111|11111110|11101 1fffdd [21]\n" +
+ " (162) |11111111|11111110|1001 fffe9 [20]\n" +
+ " (163) |11111111|11111111|011011 3fffdb [22]\n" +
+ " (164) |11111111|11111111|011100 3fffdc [22]\n" +
+ " (165) |11111111|11111111|1101000 7fffe8 [23]\n" +
+ " (166) |11111111|11111111|1101001 7fffe9 [23]\n" +
+ " (167) |11111111|11111110|11110 1fffde [21]\n" +
+ " (168) |11111111|11111111|1101010 7fffea [23]\n" +
+ " (169) |11111111|11111111|011101 3fffdd [22]\n" +
+ " (170) |11111111|11111111|011110 3fffde [22]\n" +
+ " (171) |11111111|11111111|11110000 fffff0 [24]\n" +
+ " (172) |11111111|11111110|11111 1fffdf [21]\n" +
+ " (173) |11111111|11111111|011111 3fffdf [22]\n" +
+ " (174) |11111111|11111111|1101011 7fffeb [23]\n" +
+ " (175) |11111111|11111111|1101100 7fffec [23]\n" +
+ " (176) |11111111|11111111|00000 1fffe0 [21]\n" +
+ " (177) |11111111|11111111|00001 1fffe1 [21]\n" +
+ " (178) |11111111|11111111|100000 3fffe0 [22]\n" +
+ " (179) |11111111|11111111|00010 1fffe2 [21]\n" +
+ " (180) |11111111|11111111|1101101 7fffed [23]\n" +
+ " (181) |11111111|11111111|100001 3fffe1 [22]\n" +
+ " (182) |11111111|11111111|1101110 7fffee [23]\n" +
+ " (183) |11111111|11111111|1101111 7fffef [23]\n" +
+ " (184) |11111111|11111110|1010 fffea [20]\n" +
+ " (185) |11111111|11111111|100010 3fffe2 [22]\n" +
+ " (186) |11111111|11111111|100011 3fffe3 [22]\n" +
+ " (187) |11111111|11111111|100100 3fffe4 [22]\n" +
+ " (188) |11111111|11111111|1110000 7ffff0 [23]\n" +
+ " (189) |11111111|11111111|100101 3fffe5 [22]\n" +
+ " (190) |11111111|11111111|100110 3fffe6 [22]\n" +
+ " (191) |11111111|11111111|1110001 7ffff1 [23]\n" +
+ " (192) |11111111|11111111|11111000|00 3ffffe0 [26]\n" +
+ " (193) |11111111|11111111|11111000|01 3ffffe1 [26]\n" +
+ " (194) |11111111|11111110|1011 fffeb [20]\n" +
+ " (195) |11111111|11111110|001 7fff1 [19]\n" +
+ " (196) |11111111|11111111|100111 3fffe7 [22]\n" +
+ " (197) |11111111|11111111|1110010 7ffff2 [23]\n" +
+ " (198) |11111111|11111111|101000 3fffe8 [22]\n" +
+ " (199) |11111111|11111111|11110110|0 1ffffec [25]\n" +
+ " (200) |11111111|11111111|11111000|10 3ffffe2 [26]\n" +
+ " (201) |11111111|11111111|11111000|11 3ffffe3 [26]\n" +
+ " (202) |11111111|11111111|11111001|00 3ffffe4 [26]\n" +
+ " (203) |11111111|11111111|11111011|110 7ffffde [27]\n" +
+ " (204) |11111111|11111111|11111011|111 7ffffdf [27]\n" +
+ " (205) |11111111|11111111|11111001|01 3ffffe5 [26]\n" +
+ " (206) |11111111|11111111|11110001 fffff1 [24]\n" +
+ " (207) |11111111|11111111|11110110|1 1ffffed [25]\n" +
+ " (208) |11111111|11111110|010 7fff2 [19]\n" +
+ " (209) |11111111|11111111|00011 1fffe3 [21]\n" +
+ " (210) |11111111|11111111|11111001|10 3ffffe6 [26]\n" +
+ " (211) |11111111|11111111|11111100|000 7ffffe0 [27]\n" +
+ " (212) |11111111|11111111|11111100|001 7ffffe1 [27]\n" +
+ " (213) |11111111|11111111|11111001|11 3ffffe7 [26]\n" +
+ " (214) |11111111|11111111|11111100|010 7ffffe2 [27]\n" +
+ " (215) |11111111|11111111|11110010 fffff2 [24]\n" +
+ " (216) |11111111|11111111|00100 1fffe4 [21]\n" +
+ " (217) |11111111|11111111|00101 1fffe5 [21]\n" +
+ " (218) |11111111|11111111|11111010|00 3ffffe8 [26]\n" +
+ " (219) |11111111|11111111|11111010|01 3ffffe9 [26]\n" +
+ " (220) |11111111|11111111|11111111|1101 ffffffd [28]\n" +
+ " (221) |11111111|11111111|11111100|011 7ffffe3 [27]\n" +
+ " (222) |11111111|11111111|11111100|100 7ffffe4 [27]\n" +
+ " (223) |11111111|11111111|11111100|101 7ffffe5 [27]\n" +
+ " (224) |11111111|11111110|1100 fffec [20]\n" +
+ " (225) |11111111|11111111|11110011 fffff3 [24]\n" +
+ " (226) |11111111|11111110|1101 fffed [20]\n" +
+ " (227) |11111111|11111111|00110 1fffe6 [21]\n" +
+ " (228) |11111111|11111111|101001 3fffe9 [22]\n" +
+ " (229) |11111111|11111111|00111 1fffe7 [21]\n" +
+ " (230) |11111111|11111111|01000 1fffe8 [21]\n" +
+ " (231) |11111111|11111111|1110011 7ffff3 [23]\n" +
+ " (232) |11111111|11111111|101010 3fffea [22]\n" +
+ " (233) |11111111|11111111|101011 3fffeb [22]\n" +
+ " (234) |11111111|11111111|11110111|0 1ffffee [25]\n" +
+ " (235) |11111111|11111111|11110111|1 1ffffef [25]\n" +
+ " (236) |11111111|11111111|11110100 fffff4 [24]\n" +
+ " (237) |11111111|11111111|11110101 fffff5 [24]\n" +
+ " (238) |11111111|11111111|11111010|10 3ffffea [26]\n" +
+ " (239) |11111111|11111111|1110100 7ffff4 [23]\n" +
+ " (240) |11111111|11111111|11111010|11 3ffffeb [26]\n" +
+ " (241) |11111111|11111111|11111100|110 7ffffe6 [27]\n" +
+ " (242) |11111111|11111111|11111011|00 3ffffec [26]\n" +
+ " (243) |11111111|11111111|11111011|01 3ffffed [26]\n" +
+ " (244) |11111111|11111111|11111100|111 7ffffe7 [27]\n" +
+ " (245) |11111111|11111111|11111101|000 7ffffe8 [27]\n" +
+ " (246) |11111111|11111111|11111101|001 7ffffe9 [27]\n" +
+ " (247) |11111111|11111111|11111101|010 7ffffea [27]\n" +
+ " (248) |11111111|11111111|11111101|011 7ffffeb [27]\n" +
+ " (249) |11111111|11111111|11111111|1110 ffffffe [28]\n" +
+ " (250) |11111111|11111111|11111101|100 7ffffec [27]\n" +
+ " (251) |11111111|11111111|11111101|101 7ffffed [27]\n" +
+ " (252) |11111111|11111111|11111101|110 7ffffee [27]\n" +
+ " (253) |11111111|11111111|11111101|111 7ffffef [27]\n" +
+ " (254) |11111111|11111111|11111110|000 7fffff0 [27]\n" +
+ " (255) |11111111|11111111|11111011|10 3ffffee [26]\n" +
+ " EOS (256) |11111111|11111111|11111111|111111 3fffffff [30]";
+ // @formatter:on
+
+ @Test
+ public void read_table() {
+ Pattern line = Pattern.compile(
+ "\\(\\s*(?<ascii>\\d+)\\s*\\)\\s*(?<binary>(\\|(0|1)+)+)\\s*" +
+ "(?<hex>[0-9a-zA-Z]+)\\s*\\[\\s*(?<len>\\d+)\\s*\\]");
+ Matcher m = line.matcher(SPEC);
+ int i = 0;
+ while (m.find()) {
+ String ascii = m.group("ascii");
+ String binary = m.group("binary").replaceAll("\\|", "");
+ String hex = m.group("hex");
+ String len = m.group("len");
+
+ // Several sanity checks for the data read from the table, just to
+ // make sure what we read makes sense
+ assertEquals(parseInt(len), binary.length());
+ assertEquals(parseInt(binary, 2), parseInt(hex, 16));
+
+ int expected = parseInt(ascii);
+
+ // TODO: find actual eos, do not hardcode it!
+ byte[] bytes = intToBytes(0x3fffffff, 30,
+ parseInt(hex, 16), parseInt(len));
+
+ StringBuilder actual = new StringBuilder();
+ Huffman.Reader t = new Huffman.Reader();
+ t.read(ByteBuffer.wrap(bytes), actual, false, true);
+
+ // What has been read MUST represent a single symbol
+ assertEquals(actual.length(), 1, "ascii: " + ascii);
+
+ // It's a lot more visual to compare char as codes rather than
+ // characters (as some of them might not be visible)
+ assertEquals(actual.charAt(0), expected);
+ i++;
+ }
+ assertEquals(i, 257); // 256 + EOS
+ }
+
+ //
+ // https://tools.ietf.org/html/rfc7541#appendix-C.4.1
+ //
+ @Test
+ public void read_1() {
+ read("f1e3 c2e5 f23a 6ba0 ab90 f4ff", "www.example.com");
+ }
+
+ @Test
+ public void write_1() {
+ write("www.example.com", "f1e3 c2e5 f23a 6ba0 ab90 f4ff");
+ }
+
+ //
+ // https://tools.ietf.org/html/rfc7541#appendix-C.4.2
+ //
+ @Test
+ public void read_2() {
+ read("a8eb 1064 9cbf", "no-cache");
+ }
+
+ @Test
+ public void write_2() {
+ write("no-cache", "a8eb 1064 9cbf");
+ }
+
+ //
+ // https://tools.ietf.org/html/rfc7541#appendix-C.4.3
+ //
+ @Test
+ public void read_3() {
+ read("25a8 49e9 5ba9 7d7f", "custom-key");
+ }
+
+ @Test
+ public void write_3() {
+ write("custom-key", "25a8 49e9 5ba9 7d7f");
+ }
+
+ //
+ // https://tools.ietf.org/html/rfc7541#appendix-C.4.3
+ //
+ @Test
+ public void read_4() {
+ read("25a8 49e9 5bb8 e8b4 bf", "custom-value");
+ }
+
+ @Test
+ public void write_4() {
+ write("custom-value", "25a8 49e9 5bb8 e8b4 bf");
+ }
+
+ //
+ // https://tools.ietf.org/html/rfc7541#appendix-C.6.1
+ //
+ @Test
+ public void read_5() {
+ read("6402", "302");
+ }
+
+ @Test
+ public void write_5() {
+ write("302", "6402");
+ }
+
+ //
+ // https://tools.ietf.org/html/rfc7541#appendix-C.6.1
+ //
+ @Test
+ public void read_6() {
+ read("aec3 771a 4b", "private");
+ }
+
+ @Test
+ public void write_6() {
+ write("private", "aec3 771a 4b");
+ }
+
+ //
+ // https://tools.ietf.org/html/rfc7541#appendix-C.6.1
+ //
+ @Test
+ public void read_7() {
+ read("d07a be94 1054 d444 a820 0595 040b 8166 e082 a62d 1bff",
+ "Mon, 21 Oct 2013 20:13:21 GMT");
+ }
+
+ @Test
+ public void write_7() {
+ write("Mon, 21 Oct 2013 20:13:21 GMT",
+ "d07a be94 1054 d444 a820 0595 040b 8166 e082 a62d 1bff");
+ }
+
+ //
+ // https://tools.ietf.org/html/rfc7541#appendix-C.6.1
+ //
+ @Test
+ public void read_8() {
+ read("9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 d3",
+ "https://www.example.com");
+ }
+
+ @Test
+ public void write_8() {
+ write("https://www.example.com",
+ "9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 d3");
+ }
+
+ //
+ // https://tools.ietf.org/html/rfc7541#appendix-C.6.2
+ //
+ @Test
+ public void read_9() {
+ read("640e ff", "307");
+ }
+
+ @Test
+ public void write_9() {
+ write("307", "640e ff");
+ }
+
+ //
+ // https://tools.ietf.org/html/rfc7541#appendix-C.6.3
+ //
+ @Test
+ public void read_10() {
+ read("d07a be94 1054 d444 a820 0595 040b 8166 e084 a62d 1bff",
+ "Mon, 21 Oct 2013 20:13:22 GMT");
+ }
+
+ @Test
+ public void write_10() {
+ write("Mon, 21 Oct 2013 20:13:22 GMT",
+ "d07a be94 1054 d444 a820 0595 040b 8166 e084 a62d 1bff");
+ }
+
+ //
+ // https://tools.ietf.org/html/rfc7541#appendix-C.6.3
+ //
+ @Test
+ public void read_11() {
+ read("9bd9 ab", "gzip");
+ }
+
+ @Test
+ public void write_11() {
+ write("gzip", "9bd9 ab");
+ }
+
+ //
+ // https://tools.ietf.org/html/rfc7541#appendix-C.6.3
+ //
+ @Test
+ public void read_12() {
+ read("94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 " +
+ "d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 " +
+ "3160 65c0 03ed 4ee5 b106 3d50 07",
+ "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1");
+ }
+
+ @Test
+ public void test_trie_has_no_empty_nodes() {
+ Huffman.Node root = Huffman.INSTANCE.getRoot();
+ Stack<Huffman.Node> backlog = new Stack<>();
+ backlog.push(root);
+ while (!backlog.isEmpty()) {
+ Huffman.Node n = backlog.pop();
+ // The only type of nodes we couldn't possibly catch during
+ // construction is an empty node: no children and no char
+ if (n.left != null) {
+ backlog.push(n.left);
+ }
+ if (n.right != null) {
+ backlog.push(n.right);
+ }
+ assertFalse(!n.charIsSet && n.left == null && n.right == null,
+ "Empty node in the trie");
+ }
+ }
+
+ @Test
+ public void test_trie_has_257_nodes() {
+ int count = 0;
+ Huffman.Node root = Huffman.INSTANCE.getRoot();
+ Stack<Huffman.Node> backlog = new Stack<>();
+ backlog.push(root);
+ while (!backlog.isEmpty()) {
+ Huffman.Node n = backlog.pop();
+ if (n.left != null) {
+ backlog.push(n.left);
+ }
+ if (n.right != null) {
+ backlog.push(n.right);
+ }
+ if (n.isLeaf()) {
+ count++;
+ }
+ }
+ assertEquals(count, 257);
+ }
+
+ @Test
+ public void cant_encode_outside_byte() {
+ TestHelper.Block<Object> coding =
+ () -> new Huffman.Writer()
+ .from(((char) 256) + "", 0, 1)
+ .write(ByteBuffer.allocate(1));
+ RuntimeException e =
+ TestHelper.assertVoidThrows(RuntimeException.class, coding);
+ TestHelper.assertExceptionMessageContains(e, "char");
+ }
+
+ private static void read(String hexdump, String decoded) {
+ ByteBuffer source = SpecHelper.toBytes(hexdump);
+ Appendable actual = new StringBuilder();
+ new Huffman.Reader().read(source, actual, true);
+ assertEquals(actual.toString(), decoded);
+ }
+
+ private static void write(String decoded, String hexdump) {
+ int n = Huffman.INSTANCE.lengthOf(decoded);
+ ByteBuffer destination = ByteBuffer.allocate(n); // Extra margin (1) to test having more bytes in the destination than needed is ok
+ Huffman.Writer writer = new Huffman.Writer();
+ BuffersTestingKit.forEachSplit(destination, byteBuffers -> {
+ writer.from(decoded, 0, decoded.length());
+ boolean written = false;
+ for (ByteBuffer b : byteBuffers) {
+ int pos = b.position();
+ written = writer.write(b);
+ b.position(pos);
+ }
+ assertTrue(written);
+ ByteBuffer concated = BuffersTestingKit.concat(byteBuffers);
+ String actual = SpecHelper.toHexdump(concated);
+ assertEquals(actual, hexdump);
+ writer.reset();
+ });
+ }
+
+ //
+ // It's not very pretty, yes I know that
+ //
+ // hex:
+ //
+ // |31|30|...|N-1|...|01|00|
+ // \ /
+ // codeLength
+ //
+ // hex <<= 32 - codeLength; (align to MSB):
+ //
+ // |31|30|...|32-N|...|01|00|
+ // \ /
+ // codeLength
+ //
+ // EOS:
+ //
+ // |31|30|...|M-1|...|01|00|
+ // \ /
+ // eosLength
+ //
+ // eos <<= 32 - eosLength; (align to MSB):
+ //
+ // pad with MSBs of EOS:
+ //
+ // |31|30|...|32-N|32-N-1|...|01|00|
+ // | 32|...|
+ //
+ // Finally, split into byte[]
+ //
+ private byte[] intToBytes(int eos, int eosLength, int hex, int codeLength) {
+ hex <<= 32 - codeLength;
+ eos >>= codeLength - (32 - eosLength);
+ hex |= eos;
+ int n = (int) Math.ceil(codeLength / 8.0);
+ byte[] result = new byte[n];
+ for (int i = 0; i < n; i++) {
+ result[i] = (byte) (hex >> (32 - 8 * (i + 1)));
+ }
+ return result;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/SpecHelper.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+package sun.net.httpclient.hpack;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+//
+// THIS IS NOT A TEST
+//
+public final class SpecHelper {
+
+ private SpecHelper() {
+ throw new AssertionError();
+ }
+
+ public static ByteBuffer toBytes(String hexdump) {
+ Pattern hexByte = Pattern.compile("[0-9a-fA-F]{2}");
+ List<String> bytes = new ArrayList<>();
+ Matcher matcher = hexByte.matcher(hexdump);
+ while (matcher.find()) {
+ bytes.add(matcher.group(0));
+ }
+ ByteBuffer result = ByteBuffer.allocate(bytes.size());
+ for (String f : bytes) {
+ result.put((byte) Integer.parseInt(f, 16));
+ }
+ result.flip();
+ return result;
+ }
+
+ public static String toHexdump(ByteBuffer bb) {
+ List<String> words = new ArrayList<>();
+ int i = 0;
+ while (bb.hasRemaining()) {
+ if (i % 2 == 0) {
+ words.add("");
+ }
+ byte b = bb.get();
+ String hex = Integer.toHexString(256 + Byte.toUnsignedInt(b)).substring(1);
+ words.set(i / 2, words.get(i / 2) + hex);
+ i++;
+ }
+ return words.stream().collect(Collectors.joining(" "));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/TestHelper.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2014, 2016, 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.
+ */
+package sun.net.httpclient.hpack;
+
+import org.testng.annotations.Test;
+
+import java.util.Objects;
+import java.util.Random;
+
+public final class TestHelper {
+
+ public static Random newRandom() {
+ long seed = Long.getLong("jdk.test.lib.random.seed", System.currentTimeMillis());
+ System.out.println("new java.util.Random(" + seed + ")");
+ return new Random(seed);
+ }
+
+ public static <T extends Throwable> T assertVoidThrows(Class<T> clazz, Block<?> code) {
+ return assertThrows(clazz, () -> {
+ code.run();
+ return null;
+ });
+ }
+
+ public static <T extends Throwable> T assertThrows(Class<T> clazz, ReturningBlock<?> code) {
+ Objects.requireNonNull(clazz, "clazz == null");
+ Objects.requireNonNull(code, "code == null");
+ try {
+ code.run();
+ } catch (Throwable t) {
+ if (clazz.isInstance(t)) {
+ return clazz.cast(t);
+ }
+ throw new AssertionError("Expected to catch exception of type "
+ + clazz.getCanonicalName() + ", instead caught "
+ + t.getClass().getCanonicalName(), t);
+
+ }
+ throw new AssertionError(
+ "Expected to catch exception of type " + clazz.getCanonicalName()
+ + ", but caught nothing");
+ }
+
+ public static <T> T assertDoesNotThrow(ReturningBlock<T> code) {
+ Objects.requireNonNull(code, "code == null");
+ try {
+ return code.run();
+ } catch (Throwable t) {
+ throw new AssertionError(
+ "Expected code block to exit normally, instead " +
+ "caught " + t.getClass().getCanonicalName(), t);
+ }
+ }
+
+ public static void assertVoidDoesNotThrow(Block<?> code) {
+ Objects.requireNonNull(code, "code == null");
+ try {
+ code.run();
+ } catch (Throwable t) {
+ throw new AssertionError(
+ "Expected code block to exit normally, instead " +
+ "caught " + t.getClass().getCanonicalName(), t);
+ }
+ }
+
+
+ public static void assertExceptionMessageContains(Throwable t,
+ CharSequence firstSubsequence,
+ CharSequence... others) {
+ assertCharSequenceContains(t.getMessage(), firstSubsequence, others);
+ }
+
+ public static void assertCharSequenceContains(CharSequence s,
+ CharSequence firstSubsequence,
+ CharSequence... others) {
+ if (s == null) {
+ throw new NullPointerException("Exception message is null");
+ }
+ String str = s.toString();
+ String missing = null;
+ if (!str.contains(firstSubsequence.toString())) {
+ missing = firstSubsequence.toString();
+ } else {
+ for (CharSequence o : others) {
+ if (!str.contains(o.toString())) {
+ missing = o.toString();
+ break;
+ }
+ }
+ }
+ if (missing != null) {
+ throw new AssertionError("CharSequence '" + s + "'" + " does not "
+ + "contain subsequence '" + missing + "'");
+ }
+ }
+
+ public interface ReturningBlock<T> {
+ T run() throws Throwable;
+ }
+
+ public interface Block<T> {
+ void run() throws Throwable;
+ }
+
+ // tests
+
+ @Test
+ public void assertThrows() {
+ assertThrows(NullPointerException.class, () -> ((Object) null).toString());
+ }
+
+ @Test
+ public void assertThrowsWrongType() {
+ try {
+ assertThrows(IllegalArgumentException.class, () -> ((Object) null).toString());
+ } catch (AssertionError e) {
+ Throwable cause = e.getCause();
+ String message = e.getMessage();
+ if (cause != null
+ && cause instanceof NullPointerException
+ && message != null
+ && message.contains("instead caught")) {
+ return;
+ }
+ }
+ throw new AssertionError();
+ }
+
+ @Test
+ public void assertThrowsNoneCaught() {
+ try {
+ assertThrows(IllegalArgumentException.class, () -> null);
+ } catch (AssertionError e) {
+ Throwable cause = e.getCause();
+ String message = e.getMessage();
+ if (cause == null
+ && message != null
+ && message.contains("but caught nothing")) {
+ return;
+ }
+ }
+ throw new AssertionError();
+ }
+}
--- a/jdk/test/java/security/Signature/TestInitSignWithMyOwnRandom.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/java/security/Signature/TestInitSignWithMyOwnRandom.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2015, 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
@@ -55,9 +55,9 @@
int count = 0;
- public int nextInt() {
+ @Override
+ public void nextBytes(byte[] rs) {
count++;
- return 0;
}
public boolean isUsed() {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/time/tck/java/time/format/TCKLocalizedOffsetIdPrinterParser.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+package tck.java.time.format;
+
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Locale;
+
+import org.testng.annotations.Test;
+
+/**
+ * Test localized behavior of formatter.
+ */
+@Test
+public class TCKLocalizedOffsetIdPrinterParser {
+ @Test
+ public void test_localized_offset_parse() {
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.S O")
+ .withLocale(Locale.ENGLISH);
+ String date = formatter.format(ZonedDateTime.now(ZoneOffset.UTC));
+ formatter.parse(date) ;
+ }
+}
--- a/jdk/test/java/util/ServiceLoader/modules/BasicTest.java Thu Apr 21 12:57:11 2016 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2015, 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.lang.reflect.Layer;
-import java.security.Provider;
-import java.util.ServiceLoader;
-
-import org.testng.annotations.Test;
-import static org.testng.Assert.*;
-
-/*
- * @test
- * @run testng BasicTest
- * @summary Basic test of ServiceLoader with modules
- */
-
-public class BasicTest {
-
- @Test
- public void testEmptyLayer() {
- ServiceLoader<Provider> sl
- = ServiceLoader.load(Layer.empty(), Provider.class);
- assertFalse(sl.iterator().hasNext());
- }
-
- @Test
- public void testBootLayer() {
- ServiceLoader<Provider> sl
- = ServiceLoader.load(Layer.boot(), Provider.class);
- boolean found = false;
- for (Provider provider : sl) {
- if (provider.getName().equals("SunJCE"))
- found = true;
- }
- assertTrue(found);
- }
-
- @Test(expectedExceptions = { NullPointerException.class })
- public void testNullLayer() {
- ServiceLoader.load(null, Provider.class);
- }
-
- @Test(expectedExceptions = { NullPointerException.class })
- public void testNullService() {
- ServiceLoader.load(Layer.empty(), null);
- }
-
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/ServiceLoader/modules/MiscTests.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015, 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.lang.reflect.Layer;
+import java.security.Provider;
+import java.util.ServiceLoader;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+/*
+ * @test
+ * @run testng MiscTests
+ * @summary Basic test of ServiceLoader with modules
+ */
+
+public class MiscTests {
+
+ @Test
+ public void testEmptyLayer() {
+ ServiceLoader<Provider> sl
+ = ServiceLoader.load(Layer.empty(), Provider.class);
+ assertFalse(sl.iterator().hasNext());
+ }
+
+ @Test(expectedExceptions = { NullPointerException.class })
+ public void testNullLayer() {
+ ServiceLoader.load(null, Provider.class);
+ }
+
+ @Test(expectedExceptions = { NullPointerException.class })
+ public void testNullService() {
+ ServiceLoader.load(Layer.empty(), null);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/plugins/tiff/MultiPageImageTIFFFieldTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,378 @@
+/*
+ * Copyright (c) 2016, 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
+ * @ignore 8148454
+ * @bug 8152183 8148454
+ * @author a.stepanov
+ * @summary check that TIFFields are derived properly for multi-page tiff
+ * @run main MultiPageImageTIFFFieldTest
+ */
+
+import java.awt.*;
+import java.awt.color.*;
+import java.awt.image.BufferedImage;
+import java.io.*;
+import javax.imageio.*;
+import javax.imageio.metadata.*;
+import javax.imageio.stream.*;
+import javax.imageio.plugins.tiff.*;
+
+
+public class MultiPageImageTIFFFieldTest {
+
+ private final static String FILENAME = "test.tiff";
+ private final static int W1 = 20, H1 = 40, W2 = 100, H2 = 15;
+ private final static Color C1 = Color.BLACK, C2 = Color.RED;
+
+ private final static int N_WIDTH = BaselineTIFFTagSet.TAG_IMAGE_WIDTH;
+ private final static int N_HEIGHT = BaselineTIFFTagSet.TAG_IMAGE_LENGTH;
+
+ private static final String DESCRIPTION_1[] = {"Description-1", "abc ABC"};
+ private static final String DESCRIPTION_2[] = {"Description-2", "1-2-3"};
+ private final static int N_DESCRIPTION =
+ BaselineTIFFTagSet.TAG_IMAGE_DESCRIPTION;
+
+ private final static String EXIF_DATA_1[] = {"2001:01:01 00:00:01"};
+ private final static String EXIF_DATA_2[] = {"2002:02:02 00:00:02"};
+ private final static int N_EXIF = ExifTIFFTagSet.TAG_DATE_TIME_ORIGINAL;
+
+ private final static String GPS_DATA[] = {
+ ExifGPSTagSet.STATUS_MEASUREMENT_IN_PROGRESS};
+ private final static int N_GPS = ExifGPSTagSet.TAG_GPS_STATUS;
+
+ private final static short FAX_DATA =
+ FaxTIFFTagSet.CLEAN_FAX_DATA_ERRORS_UNCORRECTED;
+ private final static int N_FAX = FaxTIFFTagSet.TAG_CLEAN_FAX_DATA;
+
+ private static final byte[] ICC_PROFILE_2 =
+ ICC_ProfileRGB.getInstance(ColorSpace.CS_sRGB).getData();
+ private static final int N_ICC = BaselineTIFFTagSet.TAG_ICC_PROFILE;
+
+ private static final int N_BPS = BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE;
+
+ private static final int
+ COMPRESSION_1 = BaselineTIFFTagSet.COMPRESSION_DEFLATE,
+ COMPRESSION_2 = BaselineTIFFTagSet.COMPRESSION_LZW;
+ private static final int N_COMPRESSION = BaselineTIFFTagSet.TAG_COMPRESSION;
+
+ private static final int
+ GRAY_1 = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO,
+ GRAY_2 = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO,
+ RGB = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_RGB;
+
+ private static final int N_PHOTO =
+ BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION;
+
+ private ImageWriter getTIFFWriter() {
+
+ java.util.Iterator<ImageWriter> writers =
+ ImageIO.getImageWritersByFormatName("TIFF");
+ if (!writers.hasNext()) {
+ throw new RuntimeException("No writers available for TIFF format");
+ }
+ return writers.next();
+ }
+
+ private ImageReader getTIFFReader() {
+
+ java.util.Iterator<ImageReader> readers =
+ ImageIO.getImageReadersByFormatName("TIFF");
+ if (!readers.hasNext()) {
+ throw new RuntimeException("No readers available for TIFF format");
+ }
+ return readers.next();
+ }
+
+ private void addASCIIField(TIFFDirectory d,
+ String name,
+ String data[],
+ int num) {
+
+ d.addTIFFField(new TIFFField(
+ new TIFFTag(name, num, 1 << TIFFTag.TIFF_ASCII),
+ TIFFTag.TIFF_ASCII, data.length, data));
+ }
+
+ private void checkASCIIField(TIFFDirectory d,
+ String what,
+ String data[],
+ int num) {
+
+ String notFound = what + " field was not found";
+ check(d.containsTIFFField(num), notFound);
+ TIFFField f = d.getTIFFField(num);
+ check(f.getType() == TIFFTag.TIFF_ASCII, "field type != ASCII");
+ check(f.getCount() == data.length, "invalid " + what + " data count");
+ for (int i = 0; i < data.length; i++) {
+ check(f.getValueAsString(i).equals(data[i]),
+ "invalid " + what + " data");
+ }
+ }
+
+ private void writeImage() throws Exception {
+
+ OutputStream s = new BufferedOutputStream(new FileOutputStream(FILENAME));
+ try (ImageOutputStream ios = ImageIO.createImageOutputStream(s)) {
+
+ ImageWriter writer = getTIFFWriter();
+ writer.setOutput(ios);
+
+ BufferedImage img1 =
+ new BufferedImage(W1, H1, BufferedImage.TYPE_BYTE_GRAY);
+ Graphics g = img1.getGraphics();
+ g.setColor(C1);
+ g.fillRect(0, 0, W1, H1);
+ g.dispose();
+
+ BufferedImage img2 =
+ new BufferedImage(W2, H2, BufferedImage.TYPE_INT_RGB);
+ g = img2.getGraphics();
+ g.setColor(C2);
+ g.fillRect(0, 0, W2, H2);
+ g.dispose();
+
+ ImageWriteParam param1 = writer.getDefaultWriteParam();
+ param1.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
+ param1.setCompressionType("Deflate");
+ param1.setCompressionQuality(0.5f);
+
+ ImageWriteParam param2 = writer.getDefaultWriteParam();
+ param2.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
+ param2.setCompressionType("LZW");
+ param2.setCompressionQuality(0.5f);
+
+ IIOMetadata
+ md1 = writer.getDefaultImageMetadata(
+ new ImageTypeSpecifier(img1), param1),
+ md2 = writer.getDefaultImageMetadata(
+ new ImageTypeSpecifier(img2), param2);
+
+ TIFFDirectory
+ dir1 = TIFFDirectory.createFromMetadata(md1),
+ dir2 = TIFFDirectory.createFromMetadata(md2);
+
+ addASCIIField(dir1, "ImageDescription", DESCRIPTION_1, N_DESCRIPTION);
+ addASCIIField(dir2, "ImageDescription", DESCRIPTION_2, N_DESCRIPTION);
+
+ addASCIIField(dir1, "GPSStatus", GPS_DATA, N_GPS);
+ addASCIIField(dir2, "GPSStatus", GPS_DATA, N_GPS);
+
+ addASCIIField(dir1, "DateTimeOriginal", EXIF_DATA_1, N_EXIF);
+ addASCIIField(dir2, "DateTimeOriginal", EXIF_DATA_2, N_EXIF);
+
+ TIFFTag faxTag = new TIFFTag(
+ "CleanFaxData", N_FAX, 1 << TIFFTag.TIFF_SHORT);
+ dir1.addTIFFField(new TIFFField(faxTag, FAX_DATA));
+ dir2.addTIFFField(new TIFFField(faxTag, FAX_DATA));
+
+ dir2.addTIFFField(new TIFFField(
+ new TIFFTag("ICC Profile", N_ICC, 1 << TIFFTag.TIFF_UNDEFINED),
+ TIFFTag.TIFF_UNDEFINED, ICC_PROFILE_2.length, ICC_PROFILE_2));
+
+ writer.prepareWriteSequence(null);
+ writer.writeToSequence(
+ new IIOImage(img1, null, dir1.getAsMetadata()), param1);
+ writer.writeToSequence(
+ new IIOImage(img2, null, dir2.getAsMetadata()), param2);
+ writer.endWriteSequence();
+
+ ios.flush();
+ writer.dispose();
+ }
+ s.close();
+ }
+
+ private void checkBufferedImages(BufferedImage im1, BufferedImage im2) {
+
+ check(im1.getWidth() == W1, "invalid width for image 1");
+ check(im1.getHeight() == H1, "invalid height for image 1");
+ check(im2.getWidth() == W2, "invalid width for image 2");
+ check(im2.getHeight() == H2, "invalid height for image 2");
+
+ Color
+ c1 = new Color(im1.getRGB(W1 / 2, H1 / 2)),
+ c2 = new Color(im2.getRGB(W2 / 2, H2 / 2));
+
+ check(c1.equals(C1), "invalid image 1 color");
+ check(c2.equals(C2), "invalid image 2 color");
+ }
+
+ private void readAndCheckImage() throws Exception {
+
+ ImageReader reader = getTIFFReader();
+
+ ImageInputStream s = ImageIO.createImageInputStream(new File(FILENAME));
+ reader.setInput(s, false, true);
+
+ int ni = reader.getNumImages(true);
+ check(ni == 2, "invalid number of images");
+
+ // check TIFFImageReadParam for multipage image
+ TIFFImageReadParam
+ param1 = new TIFFImageReadParam(), param2 = new TIFFImageReadParam();
+
+ param1.addAllowedTagSet(ExifTIFFTagSet.getInstance());
+ param1.addAllowedTagSet(ExifGPSTagSet.getInstance());
+
+ param2.addAllowedTagSet(ExifTIFFTagSet.getInstance());
+ param2.addAllowedTagSet(GeoTIFFTagSet.getInstance());
+
+ // FaxTIFFTagSet is allowed by default
+ param2.removeAllowedTagSet(FaxTIFFTagSet.getInstance());
+
+
+ // read images and metadata
+ IIOImage i1 = reader.readAll(0, param1), i2 = reader.readAll(1, param2);
+ BufferedImage
+ bi1 = (BufferedImage) i1.getRenderedImage(),
+ bi2 = (BufferedImage) i2.getRenderedImage();
+
+ // check rendered images, just in case
+ checkBufferedImages(bi1, bi2);
+
+ TIFFDirectory
+ dir1 = TIFFDirectory.createFromMetadata(i1.getMetadata()),
+ dir2 = TIFFDirectory.createFromMetadata(i2.getMetadata());
+
+ // check ASCII fields
+ checkASCIIField(
+ dir1, "image 1 description", DESCRIPTION_1, N_DESCRIPTION);
+ checkASCIIField(
+ dir2, "image 2 description", DESCRIPTION_2, N_DESCRIPTION);
+
+ checkASCIIField(dir1, "image 1 datetime", EXIF_DATA_1, N_EXIF);
+ checkASCIIField(dir2, "image 2 datetime", EXIF_DATA_2, N_EXIF);
+
+ // check sizes
+ TIFFField f = dir1.getTIFFField(N_WIDTH);
+ check((f.getCount() == 1) && (f.getAsInt(0) == W1),
+ "invalid width field for image 1");
+ f = dir2.getTIFFField(N_WIDTH);
+ check((f.getCount() == 1) && (f.getAsInt(0) == W2),
+ "invalid width field for image 2");
+
+ f = dir1.getTIFFField(N_HEIGHT);
+ check((f.getCount() == 1) && (f.getAsInt(0) == H1),
+ "invalid height field for image 1");
+ f = dir2.getTIFFField(N_HEIGHT);
+ check((f.getCount() == 1) && (f.getAsInt(0) == H2),
+ "invalid height field for image 2");
+
+ // check fax data
+ check(dir1.containsTIFFField(N_FAX), "image 2 TIFF directory " +
+ "must contain clean fax data");
+ f = dir1.getTIFFField(N_FAX);
+ check(
+ (f.getCount() == 1) && f.isIntegral() && (f.getAsInt(0) == FAX_DATA),
+ "invalid clean fax data");
+
+ check(!dir2.containsTIFFField(N_FAX), "image 2 TIFF directory " +
+ "must not contain fax fields");
+
+ // check GPS data
+ checkASCIIField(dir1, "GPS status", GPS_DATA, N_GPS);
+
+ check(!dir2.containsTIFFField(N_GPS), "image 2 TIFF directory " +
+ "must not contain GPS fields");
+
+ // check ICC profile data
+ check(!dir1.containsTIFFField(N_ICC), "image 1 TIFF directory "
+ + "must not contain ICC Profile field");
+ check(dir2.containsTIFFField(N_ICC), "image 2 TIFF directory "
+ + "must contain ICC Profile field");
+
+ f = dir2.getTIFFField(N_ICC);
+ check(f.getType() == TIFFTag.TIFF_UNDEFINED,
+ "invalid ICC profile field type");
+ int cnt = f.getCount();
+ byte icc[] = f.getAsBytes();
+ check((cnt == ICC_PROFILE_2.length) && (cnt == icc.length),
+ "invalid ICC profile");
+ for (int i = 0; i < cnt; i++) {
+ check(icc[i] == ICC_PROFILE_2[i], "invalid ICC profile data");
+ }
+
+ // check component sizes
+ check(dir1.getTIFFField(N_BPS).isIntegral() &&
+ dir2.getTIFFField(N_BPS).isIntegral(),
+ "invalid bits per sample type");
+ int sz1[] = bi1.getColorModel().getComponentSize(),
+ sz2[] = bi2.getColorModel().getComponentSize(),
+ bps1[] = dir1.getTIFFField(N_BPS).getAsInts(),
+ bps2[] = dir2.getTIFFField(N_BPS).getAsInts();
+
+ check((bps1.length == sz1.length) && (bps2.length == sz2.length),
+ "invalid component size count");
+
+ for (int i = 0; i < bps1.length; i++) {
+ check(bps1[i] == sz1[i], "image 1: invalid bits per sample data");
+ }
+
+ for (int i = 0; i < bps2.length; i++) {
+ check(bps2[i] == sz2[i], "image 2: invalid bits per sample data");
+ }
+
+ // check compression data
+ check(dir1.containsTIFFField(N_COMPRESSION) &&
+ dir2.containsTIFFField(N_COMPRESSION),
+ "compression info lost");
+ f = dir1.getTIFFField(N_COMPRESSION);
+ check(f.isIntegral() && (f.getCount() == 1) &&
+ (f.getAsInt(0) == COMPRESSION_1), "invalid image 1 compression data");
+
+ f = dir2.getTIFFField(N_COMPRESSION);
+ check(f.isIntegral() && (f.getCount() == 1) &&
+ (f.getAsInt(0) == COMPRESSION_2), "invalid image 2 compression data");
+
+ // check photometric interpretation
+ f = dir1.getTIFFField(N_PHOTO);
+ check(f.isIntegral() && (f.getCount() == 1) &&
+ ((f.getAsInt(0) == GRAY_1) || (f.getAsInt(0) == GRAY_2)),
+ "invalid photometric interpretation for image 1");
+
+ f = dir2.getTIFFField(N_PHOTO);
+ check(f.isIntegral() && (f.getCount() == 1) && (f.getAsInt(0) == RGB),
+ "invalid photometric interpretation for image 2");
+ }
+
+ public void run() {
+
+ try {
+ writeImage();
+ readAndCheckImage();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private void check(boolean ok, String msg) {
+
+ if (!ok) { throw new RuntimeException(msg); }
+ }
+
+ public static void main(String[] args) {
+ (new MultiPageImageTIFFFieldTest()).run();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/plugins/tiff/TIFFDirectoryTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2016, 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 8149028
+ * @author a.stepanov
+ * @summary some simple checks for TIFFDirectory
+ * @run main TIFFDirectoryTest
+ */
+
+import java.util.List;
+import java.util.ArrayList;
+import javax.imageio.metadata.*;
+import javax.imageio.plugins.tiff.*;
+
+
+public class TIFFDirectoryTest {
+
+ private static void check(boolean ok, String msg) {
+ if (!ok) { throw new RuntimeException(msg); }
+ }
+
+ private void run() {
+
+ int type = TIFFTag.TIFF_LONG, dt = 1 << type;
+ int n0 = 1000, n1 = 1001, n2 = 1002, n3 = 1003;
+
+ TIFFTag tag1 = new TIFFTag(Integer.toString(n1), n1, dt);
+ TIFFTag tag2 = new TIFFTag(Integer.toString(n2), n2, dt);
+ TIFFTag tag3 = new TIFFTag(Integer.toString(n3), n3, dt);
+ TIFFTag parent = new TIFFTag(Integer.toString(n0), n0, dt);
+
+ // tag sets array must not be null
+ boolean ok = false;
+ try { new TIFFDirectory(null, parent); }
+ catch (NullPointerException e) { ok = true; }
+ check(ok, "can construct TIFFDirectory with null tagsets array");
+
+ // but can be empty
+ TIFFTagSet emptySets[] = {};
+ TIFFDirectory d = new TIFFDirectory(emptySets, parent);
+ check(d.getTagSets().length == 0, "invalid number of tag sets");
+ check(d.getParentTag().getName().equals(Integer.toString(n0)) &&
+ (d.getParentTag().getNumber() == n0), "invalid parent tag");
+
+
+ // add tags
+ List<TIFFTag> tags = new ArrayList<>();
+ tags.add(tag1);
+ tags.add(tag2);
+ TIFFTagSet ts1 = new TIFFTagSet(tags);
+
+ tags.clear();
+ tags.add(tag3);
+ TIFFTagSet ts2 = new TIFFTagSet(tags);
+
+ TIFFTagSet sets[] = {ts1, ts2};
+ d = new TIFFDirectory(sets, parent);
+
+ check(d.getTagSets().length == sets.length, "invalid number of tag sets");
+
+ // check getTag()
+ for (int i = n1; i <= n3; i++) {
+ TIFFTag t = d.getTag(i);
+ check(t.getNumber() == i, "invalid tag number");
+ check(t.getName().equals(Integer.toString(i)), "invalid tag name");
+ check(t.getDataTypes() == dt, "invalid tag data types");
+ }
+
+ TIFFDirectory d2;
+ try { d2 = d.clone(); }
+ catch (CloneNotSupportedException e) { throw new RuntimeException(e); }
+
+ // check removeTagSet()
+ d.removeTagSet(ts2);
+ check(d.getTagSets().length == 1, "invalid number of tag sets");
+ check(d.getTagSets()[0].getTag(n1).getName().equals(Integer.toString(n1)),
+ "invalid tag name");
+ check(d.getTagSets()[0].getTag(n2).getName().equals(Integer.toString(n2)),
+ "invalid tag name");
+
+ d.removeTagSet(ts1);
+ check(d.getTagSets().length == 0, "invalid number of tag sets");
+
+ // check cloned data
+ check(d2.getTagSets().length == sets.length,
+ "invalid number of tag sets");
+ TIFFTagSet sets2[] = d2.getTagSets();
+ check(sets2.length == sets.length, "invalid number of tag sets");
+ check(
+ (sets2[0].getTag(Integer.toString(n1)).getNumber() == n1) &&
+ (sets2[0].getTag(Integer.toString(n2)).getNumber() == n2) &&
+ (sets2[0].getTag(Integer.toString(n0)) == null) &&
+ (sets2[1].getTag(Integer.toString(n3)).getNumber() == n3) &&
+ (sets2[1].getTag(Integer.toString(n0)) == null), "invalid data");
+
+ check(
+ (sets2[0].getTag(Integer.toString(n1)).getDataTypes() == dt) &&
+ (sets2[0].getTag(Integer.toString(n2)).getDataTypes() == dt) &&
+ (sets2[1].getTag(Integer.toString(n3)).getDataTypes() == dt),
+ "invalid data type");
+
+ // must not be able to call removeTagSet with null argument
+ ok = false;
+ try { d.removeTagSet(null); }
+ catch (NullPointerException e) { ok = true; }
+ check(ok, "must not be able to use null as an argument for remove");
+
+ // check parent tag
+ check( d.getParentTag().getName().equals(Integer.toString(n0)) &&
+ d2.getParentTag().getName().equals(Integer.toString(n0)),
+ "invalid parent tag name");
+
+ check(( d.getParentTag().getNumber() == n0) &&
+ (d2.getParentTag().getNumber() == n0),
+ "invalid parent tag number");
+
+ check(( d.getParentTag().getDataTypes() == dt) &&
+ (d2.getParentTag().getDataTypes() == dt),
+ "invalid parent data type");
+
+ d.addTagSet(ts1);
+ d.addTagSet(ts2);
+
+ // add the same tag set twice and check that nothing changed
+ d.addTagSet(ts2);
+
+ check(d.getTagSets().length == 2, "invalid number of tag sets");
+
+ // check field operations
+ check(d.getNumTIFFFields() == 0, "invalid TIFFFields number");
+ check(d.getTIFFField(Integer.MAX_VALUE) == null,
+ "must return null TIFFField");
+
+ long offset = 4L;
+ long a[] = {Long.MIN_VALUE, 0, Long.MAX_VALUE};
+ int v = 100500;
+ TIFFField
+ f1 = new TIFFField(tag1, type, offset, d),
+ f2 = new TIFFField(tag2, v),
+ f3 = new TIFFField(tag3, type, a.length, a);
+
+ d.addTIFFField(f1);
+ d.addTIFFField(f2);
+ d.addTIFFField(f3);
+
+ check(d.containsTIFFField(n1) &&
+ d.containsTIFFField(n2) &&
+ d.containsTIFFField(n3) &&
+ !d.containsTIFFField(n0), "invalid containsTIFFField() results");
+
+ check(d.getTIFFField(n0) == null, "can get unadded field");
+
+ check(d.getNumTIFFFields() == 3, "invalid TIFFFields number");
+
+ check(d.getTIFFField(n1).getCount() == 1, "invalid TIFFField count");
+ check(d.getTIFFField(n1).getAsLong(0) == offset, "invalid offset");
+
+ check(d.getTIFFField(n2).getCount() == 1, "invalid TIFFField count");
+ check(d.getTIFFField(n2).getAsInt(0) == v, "invalid TIFFField value");
+
+ check(d.getTIFFField(n3).getCount() == a.length,
+ "invalid TIFFField count");
+ for (int i = 0; i < a.length; ++i) {
+ check(d.getTIFFField(n3).getAsLong(i) == a[i],
+ "invalid TIFFField value");
+ }
+
+ TIFFField nested = d.getTIFFField(n1).getDirectory().getTIFFField(n1);
+ check(nested.getTag().getNumber() == n1, "invalid tag number");
+ check(nested.getCount() == 1, "invalid field count");
+ check(nested.getAsLong(0) == offset, "invalid offset");
+
+ // check that the field is overwritten correctly
+ int v2 = 1 << 16;
+ d.addTIFFField(new TIFFField(tag3, v2));
+ check(d.getTIFFField(n3).getCount() == 1, "invalid TIFFField count");
+ check(d.getTIFFField(n3).getAsInt(0)== v2, "invalid TIFFField value");
+ check(d.getNumTIFFFields() == 3, "invalid TIFFFields number");
+
+ // check removeTIFFField()
+ d.removeTIFFField(n3);
+ check(d.getNumTIFFFields() == 2, "invalid TIFFFields number");
+ check(d.getTIFFField(n3) == null, "can get removed field");
+
+ d.removeTIFFFields();
+ check((d.getTIFFField(n1) == null) && (d.getTIFFField(n2) == null),
+ "can get removed field");
+ check((d.getNumTIFFFields() == 0) && (d.getTIFFFields().length == 0),
+ "invalid TIFFFields number");
+
+ // check that array returned by getTIFFFields() is sorted
+ // by tag number (as it stated in the docs)
+ d.addTIFFField(f3);
+ d.addTIFFField(f1);
+ d.addTIFFField(f2);
+
+ TIFFField fa[] = d.getTIFFFields();
+ check(fa.length == 3, "invalid number of fields");
+ check((fa[0].getTagNumber() == n1) &&
+ (fa[1].getTagNumber() == n2) &&
+ (fa[2].getTagNumber() == n3),
+ "array of the fields must be sorted by tag number");
+
+ d.removeTIFFFields();
+ d.addTIFFField(f2);
+
+ // test getAsMetaData / createFromMetadata
+ try {
+ d2 = TIFFDirectory.createFromMetadata(d.getAsMetadata());
+ } catch (IIOInvalidTreeException e) {
+ throw new RuntimeException(e);
+ }
+
+ // check new data
+ check(d2.getTagSets().length == sets.length,
+ "invalid number of tag sets");
+ sets2 = d2.getTagSets();
+ check(sets2.length == sets.length, "invalid number of tag sets");
+ check(
+ (sets2[0].getTag(Integer.toString(n1)).getNumber() == n1) &&
+ (sets2[0].getTag(Integer.toString(n2)).getNumber() == n2) &&
+ (sets2[0].getTag(Integer.toString(n0)) == null) &&
+ (sets2[1].getTag(Integer.toString(n3)).getNumber() == n3) &&
+ (sets2[1].getTag(Integer.toString(n0)) == null), "invalid data");
+
+ check(
+ (sets2[0].getTag(Integer.toString(n1)).getDataTypes() == dt) &&
+ (sets2[0].getTag(Integer.toString(n2)).getDataTypes() == dt) &&
+ (sets2[1].getTag(Integer.toString(n3)).getDataTypes() == dt),
+ "invalid data type");
+
+ check(!d2.containsTIFFField(n1) &&
+ d2.containsTIFFField(n2) &&
+ !d2.containsTIFFField(n3), "invalid containsTIFFField() results");
+ check(d2.getTIFFField(n2).getCount() == 1, "invalid TIFFField count");
+ check(d2.getTIFFField(n2).getAsInt(0) == v, "invalid TIFFField value");
+
+ check((d2.getParentTag().getNumber() == n0) &&
+ d2.getParentTag().getName().equals(Integer.toString(n0)),
+ "invalid parent tag");
+ }
+
+ public static void main(String[] args) { (new TIFFDirectoryTest()).run(); }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/plugins/tiff/TIFFDirectoryWriteReadTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2016, 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 8149028
+ * @author a.stepanov
+ * @summary a simple write-read test for TIFFDirectory
+ * @run main TIFFDirectoryWriteReadTest
+ */
+
+import java.awt.*;
+import java.awt.color.*;
+import java.awt.image.BufferedImage;
+import java.io.*;
+import javax.imageio.*;
+import javax.imageio.metadata.*;
+import javax.imageio.stream.*;
+import javax.imageio.plugins.tiff.*;
+
+
+public class TIFFDirectoryWriteReadTest {
+
+ private final static String FILENAME = "test.tiff";
+ private final static int SZ = 100;
+ private final static Color C = Color.RED;
+
+ private static final String COPYRIGHT[] = {"Copyright 123ABC.."};
+ private static final String DESCRIPTION[] = {"Test Image", "Description"};
+ private static final String SOFTWARE[] = {"test", "software", "123"};
+
+ private static final long RES_X[][] = {{2, 1}}, RES_Y[][] = {{1, 1}};
+
+ private static final byte[] ICC_PROFILE =
+ ICC_ProfileRGB.getInstance(ColorSpace.CS_sRGB).getData();
+
+
+ private ImageWriter getTIFFWriter() {
+
+ java.util.Iterator<ImageWriter> writers =
+ ImageIO.getImageWritersByFormatName("TIFF");
+ if (!writers.hasNext()) {
+ throw new RuntimeException("No writers available for TIFF format");
+ }
+ return writers.next();
+ }
+
+ private ImageReader getTIFFReader() {
+
+ java.util.Iterator<ImageReader> readers =
+ ImageIO.getImageReadersByFormatName("TIFF");
+ if (!readers.hasNext()) {
+ throw new RuntimeException("No readers available for TIFF format");
+ }
+ return readers.next();
+ }
+
+ private void addASCIIField(TIFFDirectory d,
+ String name,
+ String data[],
+ int num) {
+
+ d.addTIFFField(new TIFFField(
+ new TIFFTag(name, num, 1 << TIFFTag.TIFF_ASCII),
+ TIFFTag.TIFF_ASCII, data.length, data));
+ }
+
+ private void checkASCIIField(TIFFDirectory d,
+ String what,
+ String data[],
+ int num) {
+
+ String notFound = what + " field was not found";
+ check(d.containsTIFFField(num), notFound);
+ TIFFField f = d.getTIFFField(num);
+ check(f.getType() == TIFFTag.TIFF_ASCII, "field type != ASCII");
+ check(f.getCount() == data.length, "invalid " + what + " data count");
+ for (int i = 0; i < data.length; i++) {
+ check(f.getValueAsString(i).equals(data[i]),
+ "invalid " + what + " data");
+ }
+ }
+
+ private void writeImage() throws Exception {
+
+ OutputStream s = new BufferedOutputStream(new FileOutputStream(FILENAME));
+ try (ImageOutputStream ios = ImageIO.createImageOutputStream(s)) {
+
+ ImageWriter writer = getTIFFWriter();
+ writer.setOutput(ios);
+
+ BufferedImage img = new BufferedImage(
+ SZ, SZ, BufferedImage.TYPE_INT_RGB);
+ Graphics g = img.getGraphics();
+ g.setColor(C);
+ g.fillRect(0, 0, SZ, SZ);
+ g.dispose();
+
+ IIOMetadata metadata = writer.getDefaultImageMetadata(
+ new ImageTypeSpecifier(img), writer.getDefaultWriteParam());
+
+ TIFFDirectory dir = TIFFDirectory.createFromMetadata(metadata);
+
+ addASCIIField(dir, "Copyright",
+ COPYRIGHT, BaselineTIFFTagSet.TAG_COPYRIGHT);
+
+ addASCIIField(dir, "ImageDescription",
+ DESCRIPTION, BaselineTIFFTagSet.TAG_IMAGE_DESCRIPTION);
+
+ addASCIIField(dir, "Software",
+ SOFTWARE, BaselineTIFFTagSet.TAG_SOFTWARE);
+
+ dir.addTIFFField(new TIFFField(
+ new TIFFTag("XResolution", BaselineTIFFTagSet.TAG_X_RESOLUTION,
+ 1 << TIFFTag.TIFF_RATIONAL), TIFFTag.TIFF_RATIONAL, 1, RES_X));
+ dir.addTIFFField(new TIFFField(
+ new TIFFTag("YResolution", BaselineTIFFTagSet.TAG_Y_RESOLUTION,
+ 1 << TIFFTag.TIFF_RATIONAL), TIFFTag.TIFF_RATIONAL, 1, RES_Y));
+
+ dir.addTIFFField(new TIFFField(
+ new TIFFTag("ICC Profile", BaselineTIFFTagSet.TAG_ICC_PROFILE,
+ 1 << TIFFTag.TIFF_UNDEFINED),
+ TIFFTag.TIFF_UNDEFINED, ICC_PROFILE.length, ICC_PROFILE));
+
+ IIOMetadata data = dir.getAsMetadata();
+ writer.write(new IIOImage(img, null, data));
+
+ ios.flush();
+ writer.dispose();
+ }
+ s.close();
+ }
+
+
+
+ private void readAndCheckImage() throws Exception {
+
+ ImageReader reader = getTIFFReader();
+
+ ImageInputStream s = ImageIO.createImageInputStream(new File(FILENAME));
+ reader.setInput(s);
+
+ int ni = reader.getNumImages(true);
+ check(ni == 1, "invalid number of images");
+
+ // check image
+ BufferedImage img = reader.read(0);
+ check(img.getWidth() == SZ && img.getHeight() == SZ,
+ "invalid image size");
+
+ Color c = new Color(img.getRGB(SZ / 2, SZ / 2));
+ check(C.equals(c), "invalid image color");
+
+ IIOMetadata metadata = reader.readAll(0, null).getMetadata();
+ TIFFDirectory dir = TIFFDirectory.createFromMetadata(metadata);
+
+ reader.dispose();
+ s.close();
+
+ // ===== perform tag checks =====
+
+ checkASCIIField(dir, "copyright", COPYRIGHT,
+ BaselineTIFFTagSet.TAG_COPYRIGHT);
+
+ checkASCIIField(dir, "description", DESCRIPTION,
+ BaselineTIFFTagSet.TAG_IMAGE_DESCRIPTION);
+
+ checkASCIIField(dir, "software", SOFTWARE,
+ BaselineTIFFTagSet.TAG_SOFTWARE);
+
+ TIFFField f = dir.getTIFFField(BaselineTIFFTagSet.TAG_IMAGE_WIDTH);
+ check(f.getCount() == 1, "invalid width field count");
+ int w = f.getAsInt(0);
+ check(w == SZ, "invalid width");
+
+ f = dir.getTIFFField(BaselineTIFFTagSet.TAG_IMAGE_LENGTH);
+ check(f.getCount() == 1, "invalid height field count");
+ int h = f.getAsInt(0);
+ check(h == SZ, "invalid height");
+
+ f = dir.getTIFFField(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE);
+ // RGB: 3 x 8 bits for R, G and B components
+ int bps[] = f.getAsInts();
+ check((f.getCount() == 3) && (bps.length == 3), "invalid BPS count");
+ for (int b: bps) { check(b == 8, "invalid bits per sample"); }
+
+ // RGB: PhotometricInterpretation = 2
+ f = dir.getTIFFField(BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION);
+ check(f.getCount() == 1, "invalid count");
+ check(f.getAsInt(0) == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_RGB,
+ "invalid photometric interpretation value");
+
+ String rat = " resolution must be rational";
+ f = dir.getTIFFField(BaselineTIFFTagSet.TAG_X_RESOLUTION);
+ check(f.getType() == TIFFTag.TIFF_RATIONAL, "x" + rat);
+ check(f.getCount() == 1 &&
+ f.getAsInt(0) == (int) (RES_X[0][0] / RES_X[0][1]),
+ "invalid x resolution");
+
+ f = dir.getTIFFField(BaselineTIFFTagSet.TAG_Y_RESOLUTION);
+ check(f.getType() == TIFFTag.TIFF_RATIONAL, "y" + rat);
+ check(f.getCount() == 1 &&
+ f.getAsInt(0) == (int) (RES_Y[0][0] / RES_Y[0][1]),
+ "invalid y resolution");
+
+ f = dir.getTIFFField(BaselineTIFFTagSet.TAG_ICC_PROFILE);
+ check(f.getType() == TIFFTag.TIFF_UNDEFINED,
+ "invalid ICC profile field type");
+ int cnt = f.getCount();
+ byte icc[] = f.getAsBytes();
+ check((cnt == ICC_PROFILE.length) && (cnt == icc.length),
+ "invalid ICC profile");
+ for (int i = 0; i < cnt; i++) {
+ check(icc[i] == ICC_PROFILE[i], "invalid ICC profile");
+ }
+ }
+
+ public void run() {
+
+ try {
+ writeImage();
+ readAndCheckImage();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ private void check(boolean ok, String msg) {
+ if (!ok) { throw new RuntimeException(msg); }
+ }
+
+ public static void main(String[] args) {
+ (new TIFFDirectoryWriteReadTest()).run();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/plugins/tiff/TIFFFieldTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,502 @@
+/*
+ * Copyright (c) 2016, 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 8152183
+ * @author a.stepanov
+ * @summary Some checks for TIFFField methods
+ * @run main TIFFFieldTest
+ */
+
+import java.util.List;
+import java.util.ArrayList;
+import javax.imageio.metadata.IIOMetadataNode;
+import javax.imageio.plugins.tiff.*;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+public class TIFFFieldTest {
+
+ private final static String NAME = "tag"; // tag name
+ private final static int NUM = 12345; // tag number
+ private final static int MIN_TYPE = TIFFTag.MIN_DATATYPE;
+ private final static int MAX_TYPE = TIFFTag.MAX_DATATYPE;
+ private final static String CONSTRUCT = "can construct TIFFField with ";
+
+ private void check(boolean ok, String msg) {
+ if (!ok) { throw new RuntimeException(msg); }
+ }
+
+ private void testConstructors() {
+
+ // test constructors
+
+ TIFFTag tag = new TIFFTag(
+ NAME, NUM, 1 << TIFFTag.TIFF_SHORT | 1 << TIFFTag.TIFF_LONG);
+ TIFFField f;
+
+ // constructor: TIFFField(tag, value)
+ boolean ok = false;
+ try { new TIFFField(null, 0); }
+ catch (NullPointerException e) { ok = true; }
+ check(ok, CONSTRUCT + "null tag");
+
+ ok = false;
+ try { new TIFFField(tag, -1); }
+ catch (IllegalArgumentException e) { ok = true; }
+ check(ok, CONSTRUCT + "invalid count");
+
+ // check value type recognition
+ int v = 1 << 16;
+ f = new TIFFField(tag, v - 1);
+ check(f.getType() == TIFFTag.TIFF_SHORT, "must be treated as short");
+ check(f.isIntegral(), "must be integral");
+ f = new TIFFField(tag, v);
+ check(f.getType() == TIFFTag.TIFF_LONG, "must be treated as long");
+
+ // other checks
+ check(f.getAsLongs().length == 1, "invalid long[] size");
+ check(f.isIntegral(), "must be integral");
+ check((f.getDirectory() == null) && !f.hasDirectory(),
+ "must not have directory");
+ check(f.getValueAsString(0).equals(String.valueOf(v)),
+ "invalid string representation of value");
+ check(f.getTag().getNumber() == f.getTagNumber(),
+ "invalid tag number");
+ check(f.getCount() == 1, "invalid count");
+ check(f.getTagNumber() == NUM, "invalid tag number");
+
+ // constructor: TIFFField(tag, type, count)
+ int type = TIFFTag.TIFF_SHORT;
+
+ ok = false;
+ try { new TIFFField(null, type, 1); }
+ catch (NullPointerException e) { ok = true; }
+ check(ok, CONSTRUCT + "null tag");
+
+ ok = false;
+ try { new TIFFField(tag, MAX_TYPE + 1, 1); }
+ catch (IllegalArgumentException e) { ok = true; }
+ check(ok, CONSTRUCT + "invalid type tag");
+
+ // check that count == 1 for TIFF_IFD_POINTER
+ ok = false;
+ try { new TIFFField(tag, TIFFTag.TIFF_IFD_POINTER, 0); }
+ catch (IllegalArgumentException e) { ok = true; }
+ check(ok, "only count = 1 should be allowed for IFDPointer");
+
+ ok = false;
+ try { new TIFFField(tag, TIFFTag.TIFF_IFD_POINTER, 2); }
+ catch (IllegalArgumentException e) { ok = true; }
+ check(ok, "only count = 1 should be allowed for IFDPointer");
+
+ // check that count == 0 is not allowed for TIFF_RATIONAL, TIFF_SRATIONAL
+ // (see fix for JDK-8149120)
+ ok = false;
+ try { new TIFFField(tag, TIFFTag.TIFF_RATIONAL, 0); }
+ catch (IllegalArgumentException e) { ok = true; }
+ check(ok, "count = 0 should not be allowed for Rational");
+
+ ok = false;
+ try { new TIFFField(tag, TIFFTag.TIFF_SRATIONAL, 0); }
+ catch (IllegalArgumentException e) { ok = true; }
+ check(ok, "count = 0 should not be allowed for SRational");
+
+ ok = false;
+ try { new TIFFField(tag, type, -1); }
+ catch (IllegalArgumentException e) { ok = true; }
+ check(ok, CONSTRUCT + "with invalid data count");
+
+ f = new TIFFField(tag, type, 0);
+ check(f.getCount() == 0, "invalid count");
+ check(!f.hasDirectory(), "must not have directory");
+
+ // constructor: TIFFField(tag, type, count, data)
+ double a[] = {0.1, 0.2, 0.3};
+ ok = false;
+ try { new TIFFField(null, TIFFTag.TIFF_DOUBLE, a.length, a); }
+ catch (NullPointerException e) { ok = true; }
+ check(ok, CONSTRUCT + "null tag");
+
+ ok = false;
+ try { new TIFFField(tag, type, a.length - 1, a); }
+ catch (IllegalArgumentException e) { ok = true; }
+ check(ok, CONSTRUCT + "invalid data count");
+
+ String a2[] = {"one", "two"};
+ ok = false;
+ try { new TIFFField(tag, type, 2, a2); }
+ catch (IllegalArgumentException e) { ok = true; }
+ check(ok, CONSTRUCT + "invalid data type");
+ check((f.getDirectory() == null) && !f.hasDirectory(),
+ "must not have directory");
+
+ // constructor: TIFFField(tag, type, offset, dir)
+ List<TIFFTag> tags = new ArrayList<>();
+ tags.add(tag);
+ TIFFTagSet sets[] = {new TIFFTagSet(tags)};
+ TIFFDirectory dir = new TIFFDirectory(sets, null);
+
+ ok = false;
+ try { new TIFFField(null, type, 4L, dir); }
+ catch (NullPointerException e) { ok = true; }
+ check(ok, CONSTRUCT + "null tag");
+
+ ok = false;
+ try { new TIFFField(tag, type, 0L, dir); }
+ catch (IllegalArgumentException e) { ok = true; }
+ check(ok, CONSTRUCT + "non-positive offset");
+
+ long offset = 4;
+
+ for (int t = MIN_TYPE; t <= MAX_TYPE; t++) {
+
+ tag = new TIFFTag(NAME, NUM, 1 << t);
+
+ // only TIFF_LONG and TIFF_IFD_POINTER types are allowed
+ if (t == TIFFTag.TIFF_LONG || t == TIFFTag.TIFF_IFD_POINTER) {
+
+ f = new TIFFField(tag, t, offset, dir);
+ check(f.hasDirectory(), "must have directory");
+
+ check(f.getDirectory().getTag(NUM).getName().equals(NAME),
+ "invalid tag name");
+
+ check(f.getCount() == 1, "invalid count");
+ check(f.getAsLong(0) == offset, "invalid offset");
+ } else {
+ ok = false;
+ try { new TIFFField(tag, t, offset, dir); }
+ catch (IllegalArgumentException e) { ok = true; }
+ check(ok, CONSTRUCT + "invalid data type");
+ }
+ }
+
+ type = TIFFTag.TIFF_IFD_POINTER;
+ tag = new TIFFTag(NAME, NUM, 1 << type);
+ ok = false;
+ try { new TIFFField(tag, type, offset, null); }
+ catch (NullPointerException e) { ok = true; }
+ check(ok, CONSTRUCT + "null TIFFDirectory");
+
+ type = TIFFTag.TIFF_LONG;
+ tag = new TIFFTag(NAME, NUM, 1 << type);
+ ok = false;
+ try { new TIFFField(tag, type, offset, null); }
+ catch (NullPointerException e) { ok = true; }
+ check(ok, CONSTRUCT + "null TIFFDirectory");
+ }
+
+ private void testTypes() {
+
+ // test getTypeName(), getTypeByName() methods
+
+ boolean ok = false;
+ try { TIFFField.getTypeName(MIN_TYPE - 1); }
+ catch (IllegalArgumentException e) { ok = true; }
+ check(ok, "invalid data type number used");
+
+ ok = false;
+ try { TIFFField.getTypeName(MAX_TYPE + 1); }
+ catch (IllegalArgumentException e) { ok = true; }
+ check(ok, "invalid data type number used");
+
+ for (int type = MIN_TYPE; type <= MAX_TYPE; type++) {
+ String name = TIFFField.getTypeName(type);
+ check(TIFFField.getTypeByName(name) == type, "invalid type");
+ }
+
+ for (int type = MIN_TYPE; type <= MAX_TYPE; type++) {
+
+ TIFFTag tag = new TIFFTag(NAME, NUM, 1 << type);
+ TIFFField f = new TIFFField(tag, type, 1);
+ check(f.getType() == type, "invalid type");
+
+ // check that invalid data types can not be used
+ for (int type2 = MIN_TYPE; type2 <= MAX_TYPE; ++type2) {
+ if (type2 != type) {
+ ok = false;
+ try { new TIFFField(tag, type2, 1); } // invalid type
+ catch (IllegalArgumentException e) { ok = true; }
+ check(ok, "invalid type was successfully set");
+ }
+ }
+ }
+ }
+
+ private void testGetAs() {
+
+ // test getAs...() methods
+
+ int type = TIFFTag.TIFF_SHORT;
+ TIFFTag tag = new TIFFTag(NAME, NUM, 1 << TIFFTag.TIFF_SHORT);
+
+ short v = 123;
+ TIFFField f = new TIFFField(tag, v);
+
+ check(f.getAsInt(0) == (int) v, "invalid int value");
+ check(f.getAsLong(0) == (long) v, "invalid long value");
+ check(f.getAsFloat(0) == (float) v, "invalid float value");
+ check(f.getAsDouble(0) == (double) v, "invalid double value");
+ check(f.getValueAsString(0).equals(Short.toString(v)),
+ "invalid string representation");
+
+ check(f.getAsInts().length == 1, "inavlid array size");
+ check((int) v == f.getAsInts()[0], "invalid int value");
+
+ float fa[] = {0.01f, 1.01f};
+ type = TIFFTag.TIFF_FLOAT;
+ f = new TIFFField(
+ new TIFFTag(NAME, NUM, 1 << type), type, fa.length, fa);
+ check(f.getCount() == fa.length, "invalid count");
+ float fa2[] = f.getAsFloats();
+ check(fa2.length == fa.length, "invalid array size");
+
+ for (int i = 0; i < fa.length; i++) {
+ check(fa2[i] == fa[i], "invalid value");
+ check(f.getAsDouble(i) == fa[i], "invalid value");
+ check(f.getAsInt(i) == (int) fa[i], "invalid value"); // cast to int
+ check(f.getValueAsString(i).equals(Float.toString(fa[i])),
+ "invalid string representation");
+ }
+
+ byte ba[] = {-1, -10, -100};
+ type = TIFFTag.TIFF_BYTE;
+ f = new TIFFField(
+ new TIFFTag(NAME, NUM, 1 << type), type, ba.length, ba);
+ check(f.getCount() == ba.length, "invalid count");
+ byte ba2[] = f.getAsBytes();
+ check(ba2.length == ba.length, "invalid count");
+
+ for (int i = 0; i < ba.length; i++) {
+ check(ba[i] == ba2[i], "invalid value");
+ check(ba[i] == (byte) f.getAsDouble(i), "invalid value");
+ check(ba[i] == (byte) f.getAsLong(i), "invalid value");
+
+ int unsigned = ba[i] & 0xff;
+ check(f.getAsInt(i) == unsigned, "must be treated as unsigned");
+ }
+
+ char ca[] = {'a', 'z', 0xffff};
+ type = TIFFTag.TIFF_SHORT;
+ f = new TIFFField(
+ new TIFFTag(NAME, NUM, 1 << type), type, ca.length, ca);
+ check(f.getCount() == ca.length, "invalid count");
+ char ca2[] = f.getAsChars();
+ check(ba2.length == ba.length, "invalid count");
+
+ for (int i = 0; i < ca.length; i++) {
+ check(ca[i] == ca2[i], "invalid value");
+ check(ca[i] == (char) f.getAsDouble(i), "invalid value");
+ check(ca[i] == (char) f.getAsLong(i), "invalid value");
+ check(ca[i] == (char) f.getAsInt(i), "invalid value");
+ }
+
+ type = TIFFTag.TIFF_DOUBLE;
+ double da[] = {0.1, 0.2, 0.3};
+ f = new TIFFField(
+ new TIFFTag(NAME, NUM, 1 << type), type, da.length, da);
+ check(!f.isIntegral(), "isIntegral must be false");
+
+ double da2[] = f.getAsDoubles();
+ check(f.getData() instanceof double[], "invalid data type");
+ double da3[] = (double[]) f.getData();
+ check((da.length == da2.length) &&
+ (da.length == da2.length) &&
+ (da.length == f.getCount()),
+ "invalid data count");
+ for (int i = 0; i < da.length; ++i) {
+ check(da[i] == da2[i], "invalid data");
+ check(da[i] == da3[i], "invalid data");
+ }
+
+ boolean ok = false;
+ try { f.getAsShorts(); }
+ catch (ClassCastException e) { ok = true; }
+ check(ok, "invalid data cast");
+
+ ok = false;
+ try { f.getAsRationals(); }
+ catch (ClassCastException e) { ok = true; }
+ check(ok, "invalid data cast");
+
+ ok = false;
+ try { TIFFField.createArrayForType(TIFFTag.MIN_DATATYPE - 1, 1); }
+ catch (IllegalArgumentException e) { ok = true; }
+ check(ok, "can create array with invalid datatype");
+
+ ok = false;
+ try { TIFFField.createArrayForType(TIFFTag.MAX_DATATYPE + 1, 1); }
+ catch (IllegalArgumentException e) { ok = true; }
+ check(ok, "can create array with invalid datatype");
+
+ ok = false;
+ try { TIFFField.createArrayForType(TIFFTag.TIFF_FLOAT, -1); }
+ catch (IllegalArgumentException e) { ok = true; }
+ check(ok, "can create array with negative count");
+
+ int n = 3;
+ Object
+ RA = TIFFField.createArrayForType(TIFFTag.TIFF_RATIONAL, n),
+ SRA = TIFFField.createArrayForType(TIFFTag.TIFF_SRATIONAL, n);
+ check(RA instanceof long[][], "invalid data type");
+ check(SRA instanceof int[][], "invalid data type");
+
+ long ra[][] = (long[][]) RA;
+ int sra[][] = (int[][]) SRA;
+ check((ra.length == n) && (sra.length == n), "invalid data size");
+ for (int i = 0; i < n; i++) {
+ check((ra[i].length == 2) && (sra[i].length == 2),
+ "invalid data size");
+ ra[i][0] = 1; ra[i][1] = 5 + i;
+ sra[i][0] = -1; sra[i][1] = 5 + i;
+ }
+
+ type = TIFFTag.TIFF_RATIONAL;
+ TIFFField f1 = new TIFFField(
+ new TIFFTag(NAME, NUM, 1 << type), type, n, ra);
+ type = TIFFTag.TIFF_SRATIONAL;
+ TIFFField f2 = new TIFFField(
+ new TIFFTag(NAME, NUM, 1 << type), type, n, sra);
+
+ check((f1.getCount() == ra.length) && (f2.getCount() == sra.length),
+ "invalid data count");
+
+ check(f1.getAsRationals().length == n, "invalid data count");
+ check(f2.getAsSRationals().length == n, "invalid data count");
+ for (int i = 0; i < n; i++) {
+ long r[] = f1.getAsRational(i);
+ check(r.length == 2, "invalid data format");
+ check((r[0] == 1) && (r[1] == i + 5), "invalid data");
+
+ int sr[] = f2.getAsSRational(i);
+ check(sr.length == 2, "invalid data format");
+ check((sr[0] == -1) && (sr[1] == i + 5), "invalid data");
+
+ // check string representation
+ String s = Long.toString(r[0]) + "/" + Long.toString(r[1]);
+ check(s.equals(f1.getValueAsString(i)),
+ "invalid string representation");
+
+ s = Integer.toString(sr[0]) + "/" + Integer.toString(sr[1]);
+ check(s.equals(f2.getValueAsString(i)),
+ "invalid string representation");
+
+ // see the documentation for getAsInt:
+ // TIFF_SRATIONAL or TIFF_RATIONAL format are evaluated
+ // by dividing the numerator into the denominator using
+ // double-precision arithmetic and then casting to int
+ check(f1.getAsInt(i) == (int)(r[0] / r[1]),
+ "invalid result for getAsInt");
+ check(f2.getAsInt(i) == (int)(r[0] / r[1]),
+ "invalid result for getAsInt");
+ }
+
+ ok = false;
+ try { f1.getAsRational(ra.length); }
+ catch (ArrayIndexOutOfBoundsException e) { ok = true; }
+ check(ok, "invalid index");
+
+ String sa[] = {"-1.e-25", "22", "-1.23E5"};
+ type = TIFFTag.TIFF_ASCII;
+ f = new TIFFField(
+ new TIFFTag(NAME, NUM, 1 << type), type, sa.length, sa);
+
+ // test clone() method
+ TIFFField cloned = null;
+ try { cloned = f.clone(); } catch (CloneNotSupportedException e) {
+ throw new RuntimeException(e);
+ }
+
+ check(f.getCount() == cloned.getCount(), "invalid cloned field count");
+
+ check(f.getCount() == sa.length, "invalid data count");
+ for (int i = 0; i < sa.length; i++) {
+ check(sa[i].equals(f.getAsString(i)), "invalid data");
+ // see docs: "data in TIFF_ASCII format will be parsed as by
+ // the Double.parseDouble method, with the result cast to int"
+ check(f.getAsInt(i) ==
+ (int) Double.parseDouble(sa[i]), "invalid data");
+ check(f.getAsDouble(i) == Double.parseDouble(sa[i]), "invalid data");
+
+ check(sa[i].equals(cloned.getAsString(i)), "invalid cloned data");
+ }
+ }
+
+ private void testCreateFromNode() {
+
+ int type = TIFFTag.TIFF_LONG;
+
+ List<TIFFTag> tags = new ArrayList<>();
+ int v = 1234567;
+ TIFFTag tag = new TIFFTag(NAME, NUM, 1 << type);
+ tags.add(tag);
+ TIFFTagSet ts = new TIFFTagSet(tags);
+
+ boolean ok = false;
+ try { TIFFField.createFromMetadataNode(ts, null); }
+ catch (NullPointerException e) { ok = true; }
+ check(ok, "can create TIFFField from a null node");
+
+ TIFFField f = new TIFFField(tag, v);
+ Node node = f.getAsNativeNode();
+ check(node.getNodeName().equals(f.getClass().getSimpleName()),
+ "invalid node name");
+
+ NamedNodeMap attrs = node.getAttributes();
+ for (int i = 0; i < attrs.getLength(); i++) {
+ String an = attrs.item(i).getNodeName().toLowerCase();
+ String av = attrs.item(i).getNodeValue();
+ if (an.contains("name")) {
+ check(av.equals(NAME), "invalid tag name");
+ } else if (an.contains("number")) {
+ check(av.equals(Integer.toString(NUM)), "invalid tag number");
+ }
+ }
+
+ // invalid node
+ IIOMetadataNode nok = new IIOMetadataNode("NOK");
+
+ ok = false;
+ try { TIFFField.createFromMetadataNode(ts, nok); }
+ catch (IllegalArgumentException e) { ok = true; }
+ check(ok, CONSTRUCT + "invalid node name");
+
+ TIFFField f2 = TIFFField.createFromMetadataNode(ts, node);
+ check(f2.getType() == type, "invalid type");
+ check(f2.getTagNumber() == NUM, "invalid tag number");
+ check(f2.getTag().getName().equals(NAME), "invalid tag name");
+ check(f2.getCount() == 1, "invalid count");
+ check(f2.getAsInt(0) == v, "invalid value");
+ }
+
+ public static void main(String[] args) {
+
+ TIFFFieldTest test = new TIFFFieldTest();
+ test.testConstructors();
+ test.testCreateFromNode();
+ test.testTypes();
+ test.testGetAs();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/plugins/tiff/TIFFImageReadParamTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2016, 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 8149028
+ * @author a.stepanov
+ * @summary check TIFFDirectory manipulation
+ * by means of TIFFImageReadParam
+ * @run main TIFFImageReadParamTest
+ */
+
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.image.BufferedImage;
+import java.io.*;
+import javax.imageio.*;
+import javax.imageio.metadata.IIOMetadata;
+import javax.imageio.plugins.tiff.*;
+import javax.imageio.stream.ImageInputStream;
+import javax.imageio.stream.ImageOutputStream;
+
+public class TIFFImageReadParamTest {
+
+ private final static String FILENAME = "test.tiff";
+ private final static int SZ = 100;
+ private final static Color C = Color.RED;
+
+ private final static String GEO_DATA = "test params";
+ private final static int GEO_N = GeoTIFFTagSet.TAG_GEO_ASCII_PARAMS;
+
+ private final static String EXIF_DATA = "2000:01:01 00:00:01";
+ private final static int EXIF_N = ExifTIFFTagSet.TAG_DATE_TIME_ORIGINAL;
+
+ private final static String GPS_DATA =
+ ExifGPSTagSet.STATUS_MEASUREMENT_IN_PROGRESS;
+ private final static int GPS_N = ExifGPSTagSet.TAG_GPS_STATUS;
+
+ private final static short FAX_DATA =
+ FaxTIFFTagSet.CLEAN_FAX_DATA_ERRORS_UNCORRECTED;
+ private final static int FAX_N = FaxTIFFTagSet.TAG_CLEAN_FAX_DATA;
+
+ private ImageWriter getTIFFWriter() {
+
+ java.util.Iterator<ImageWriter> writers =
+ ImageIO.getImageWritersByFormatName("TIFF");
+ if (!writers.hasNext()) {
+ throw new RuntimeException("No writers available for TIFF format");
+ }
+ return writers.next();
+ }
+
+ private ImageReader getTIFFReader() {
+
+ java.util.Iterator<ImageReader> readers =
+ ImageIO.getImageReadersByFormatName("TIFF");
+ if (!readers.hasNext()) {
+ throw new RuntimeException("No readers available for TIFF format");
+ }
+ return readers.next();
+ }
+
+ private void check(boolean ok, String msg) {
+ if (!ok) { throw new RuntimeException(msg); }
+ }
+
+ private void addASCIIField(TIFFDirectory d,
+ String name,
+ String data,
+ int num) {
+
+ String a[] = {data};
+ d.addTIFFField(new TIFFField(
+ new TIFFTag(name, num, 1 << TIFFTag.TIFF_ASCII),
+ TIFFTag.TIFF_ASCII, 1, a));
+ }
+
+ private void checkASCIIValue(TIFFDirectory d,
+ String what,
+ String data,
+ int num) {
+
+ TIFFField f = d.getTIFFField(num);
+ check(f.getType() == TIFFTag.TIFF_ASCII, "field type != ASCII");
+ check(f.getCount() == 1, "invalid " + what + " data count");
+ check(f.getValueAsString(0).equals(data),
+ "invalid " + what + " data");
+ }
+
+
+ private void writeImage() throws Exception {
+
+ OutputStream s = new BufferedOutputStream(new FileOutputStream(FILENAME));
+ try (ImageOutputStream ios = ImageIO.createImageOutputStream(s)) {
+ ImageWriter writer = getTIFFWriter();
+ writer.setOutput(ios);
+
+ BufferedImage img =
+ new BufferedImage(SZ, SZ, BufferedImage.TYPE_INT_RGB);
+ Graphics g = img.getGraphics();
+ g.setColor(C);
+ g.fillRect(0, 0, SZ, SZ);
+ g.dispose();
+
+ IIOMetadata metadata = writer.getDefaultImageMetadata(
+ new ImageTypeSpecifier(img), writer.getDefaultWriteParam());
+
+ TIFFDirectory dir = TIFFDirectory.createFromMetadata(metadata);
+
+ // add some extension tags
+ addASCIIField(dir, "GeoAsciiParamsTag", GEO_DATA, GEO_N);
+ addASCIIField(dir, "DateTimeOriginal", EXIF_DATA, EXIF_N);
+ addASCIIField(dir, "GPSStatus", GPS_DATA, GPS_N);
+
+ dir.addTIFFField(new TIFFField(new TIFFTag(
+ "CleanFaxData", FAX_N, 1 << TIFFTag.TIFF_SHORT), FAX_DATA));
+
+ IIOMetadata data = dir.getAsMetadata();
+
+ writer.write(new IIOImage(img, null, data));
+
+ ios.flush();
+ writer.dispose();
+ }
+ }
+
+ private void checkImage(BufferedImage img) {
+
+ check(img.getWidth() == SZ, "invalid image width");
+ check(img.getHeight() == SZ, "invalid image height");
+ Color c = new Color(img.getRGB(SZ / 2, SZ / 2));
+ check(c.equals(C), "invalid image color");
+ }
+
+ private TIFFDirectory getDir(TIFFTagSet[] add,
+ TIFFTagSet[] remove) throws Exception {
+
+ ImageReader reader = getTIFFReader();
+
+ ImageInputStream s = ImageIO.createImageInputStream(new File(FILENAME));
+ reader.setInput(s, false, true);
+
+ int ni = reader.getNumImages(true);
+ check(ni == 1, "invalid number of images: " + ni);
+
+ TIFFImageReadParam param = new TIFFImageReadParam();
+ for (TIFFTagSet ts: add) { param.addAllowedTagSet(ts); }
+ for (TIFFTagSet ts: remove) { param.removeAllowedTagSet(ts); }
+
+ IIOImage img = reader.readAll(0, param);
+
+ // just in case, check image
+ checkImage((BufferedImage) img.getRenderedImage());
+
+ IIOMetadata metadata = img.getMetadata();
+ TIFFDirectory dir = TIFFDirectory.createFromMetadata(metadata);
+
+ reader.dispose();
+ s.close();
+
+ return dir;
+ }
+
+ private void simpleChecks() {
+
+ TIFFImageReadParam param = new TIFFImageReadParam();
+
+ java.util.List<TIFFTagSet> allowed = param.getAllowedTagSets();
+
+ // see docs
+ check(allowed.contains(BaselineTIFFTagSet.getInstance()),
+ "must contain BaselineTIFFTagSet");
+ check(allowed.contains(FaxTIFFTagSet.getInstance()),
+ "must contain FaxTIFFTagSet");
+ check(allowed.contains(ExifParentTIFFTagSet.getInstance()),
+ "must contain ExifParentTIFFTagSet");
+ check(allowed.contains(GeoTIFFTagSet.getInstance()),
+ "must contain GeoTIFFTagSet");
+
+ TIFFTagSet gps = ExifGPSTagSet.getInstance();
+ param.addAllowedTagSet(gps);
+ check(param.getAllowedTagSets().contains(gps),
+ "must contain ExifGPSTagSet");
+
+ param.removeAllowedTagSet(gps);
+ check(!param.getAllowedTagSets().contains(gps),
+ "must not contain ExifGPSTagSet");
+
+ // check that repeating remove goes properly
+ param.removeAllowedTagSet(gps);
+
+ boolean ok = false;
+ try { param.addAllowedTagSet(null); }
+ catch (IllegalArgumentException e) { ok = true; }
+ check(ok, "must not be able to add null tag set");
+
+ ok = false;
+ try { param.removeAllowedTagSet(null); }
+ catch (IllegalArgumentException e) { ok = true; }
+ check(ok, "must not be able to remove null tag set");
+ }
+
+ private void run() {
+
+ simpleChecks();
+
+ try {
+
+ writeImage();
+
+ TIFFTagSet
+ empty[] = {},
+ geo[] = { GeoTIFFTagSet.getInstance() },
+ exif[] = { ExifTIFFTagSet.getInstance() },
+ gps[] = { ExifGPSTagSet.getInstance() },
+ fax[] = { FaxTIFFTagSet.getInstance() };
+
+ // default param state
+ TIFFDirectory dir = getDir(empty, empty);
+ // Geo and Fax are default allowed tag sets
+ check(dir.containsTIFFField(GEO_N), "must contain Geo field");
+ checkASCIIValue(dir, "Geo", GEO_DATA, GEO_N);
+ check(dir.containsTIFFField(FAX_N), "must contain Fax field");
+ check(
+ (dir.getTIFFField(FAX_N).getCount() == 1) &&
+ (dir.getTIFFField(FAX_N).getAsInt(0) == FAX_DATA),
+ "invalid Fax field value");
+
+ // corresponding tag sets are non-default
+ check(!dir.containsTIFFField(EXIF_N), "must not contain Geo field");
+ check(!dir.containsTIFFField(GPS_N), "must not contain GPS field");
+
+ // remove Fax
+ dir = getDir(empty, fax);
+ check(!dir.containsTIFFField(FAX_N), "must not contain Fax field");
+
+ // add EXIF, remove Geo
+ dir = getDir(exif, geo);
+ check(dir.containsTIFFField(EXIF_N), "must contain EXIF field");
+ checkASCIIValue(dir, "EXIF", EXIF_DATA, EXIF_N);
+ check(!dir.containsTIFFField(GEO_N), "must not contain Geo field");
+
+ // add GPS
+ dir = getDir(gps, empty);
+ check(dir.containsTIFFField(GPS_N), "must contain GPS field");
+ checkASCIIValue(dir, "GPS", GPS_DATA, GPS_N);
+
+ } catch (Exception e) { throw new RuntimeException(e); }
+ }
+
+ public static void main(String[] args) {
+ (new TIFFImageReadParamTest()).run();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/stream/NullStreamCheckTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2016, 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 8044289
+ * @summary Test verifies that when some of the read() and write() methods
+ * are not able to get stream from createImageInputStream() and
+ * createImageOutputStream() are we doing null check for stream
+ * and throwing IOException as per specification.
+ * @run main NullStreamCheckTest
+ */
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import javax.imageio.ImageIO;
+import javax.imageio.spi.IIORegistry;
+import javax.imageio.spi.ImageInputStreamSpi;
+import javax.imageio.spi.ImageOutputStreamSpi;
+
+public class NullStreamCheckTest {
+
+ // get ImageIORegistry default instance.
+ private static final IIORegistry localRegistry = IIORegistry.
+ getDefaultInstance();
+ // stream variables needed for input and output.
+ static LocalOutputStream outputStream = new LocalOutputStream();
+ static LocalInputStream inputStream = new LocalInputStream();
+
+ static final int width = 50, height = 50;
+
+ // input and output BufferedImage needed while read and write.
+ static BufferedImage inputImage = new BufferedImage(width, height,
+ BufferedImage.TYPE_INT_ARGB);
+
+ // creates test file needed for read and write in local directory.
+ private static File createTestFile(String name) throws IOException {
+ String sep = System.getProperty("file.separator");
+ String dir = System.getProperty("test.src", ".");
+ String filePath = dir+sep;
+ File directory = new File(filePath);
+ File tmpTestFile = File.createTempFile(name, ".png", directory);
+ directory.delete();
+ return tmpTestFile;
+ }
+
+ /* if we catch expected IOException message return
+ * false otherwise return true.
+ */
+ private static boolean verifyOutputExceptionMessage(IOException ex) {
+ String message = ex.getMessage();
+ return (!message.equals("Can't create an ImageOutputStream!"));
+ }
+
+ /* if we catch expected IOException message return
+ * false otherwise return true.
+ */
+ private static boolean verifyInputExceptionMessage(IOException ex) {
+ String message = ex.getMessage();
+ return (!message.equals("Can't create an ImageInputStream!"));
+ }
+
+ private static void verifyFileWrite() throws IOException {
+ File outputTestFile = createTestFile("outputTestFile");
+ try {
+ ImageIO.write(inputImage, "png", outputTestFile);
+ } catch (IOException ex) {
+ if (verifyOutputExceptionMessage(ex))
+ throw ex;
+ } finally {
+ outputTestFile.delete();
+ }
+ }
+
+ private static void verifyStreamWrite() throws IOException {
+ try {
+ ImageIO.write(inputImage, "png", outputStream);
+ } catch (IOException ex) {
+ if (verifyOutputExceptionMessage(ex))
+ throw ex;
+ } finally {
+ try {
+ outputStream.close();
+ } catch (IOException ex) {
+ throw ex;
+ }
+ }
+ }
+
+ private static void verifyFileRead() throws IOException {
+ File inputTestFile = createTestFile("inputTestFile");
+ try {
+ ImageIO.read(inputTestFile);
+ } catch (IOException ex) {
+ if (verifyInputExceptionMessage(ex))
+ throw ex;
+ } finally {
+ inputTestFile.delete();
+ }
+ }
+
+ private static void verifyStreamRead() throws IOException {
+ try {
+ ImageIO.read(inputStream);
+ } catch (IOException ex) {
+ if (verifyInputExceptionMessage(ex))
+ throw ex;
+ } finally {
+ try {
+ inputStream.close();
+ } catch (IOException ex) {
+ throw ex;
+ }
+ }
+ }
+
+ private static void verifyUrlRead() throws IOException {
+ URL url;
+ File inputTestUrlFile = createTestFile("inputTestFile");
+ try {
+ try {
+ url = inputTestUrlFile.toURI().toURL();
+ } catch (MalformedURLException ex) {
+ throw ex;
+ }
+
+ try {
+ ImageIO.read(url);
+ } catch (IOException ex) {
+ if (verifyInputExceptionMessage(ex))
+ throw ex;
+ }
+ } finally {
+ inputTestUrlFile.delete();
+ }
+ }
+
+ public static void main(String[] args) throws IOException,
+ MalformedURLException {
+
+ /* deregister ImageOutputStreamSpi so that we creatImageOutputStream
+ * returns null while writing.
+ */
+ localRegistry.deregisterAll(ImageOutputStreamSpi.class);
+ /* verify possible ImageIO.write() scenario's for null stream output
+ * from createImageOutputStream() API in ImageIO class.
+ */
+ verifyFileWrite();
+ verifyStreamWrite();
+
+ /* deregister ImageInputStreamSpi so that we creatImageInputStream
+ * returns null while reading.
+ */
+ localRegistry.deregisterAll(ImageInputStreamSpi.class);
+ /* verify possible ImageIO.read() scenario's for null stream output
+ * from createImageInputStream API in ImageIO class.
+ */
+ verifyFileRead();
+ verifyStreamRead();
+ verifyUrlRead();
+ }
+
+ static class LocalOutputStream extends OutputStream {
+
+ @Override
+ public void write(int i) throws IOException {
+ }
+ }
+
+ static class LocalInputStream extends InputStream {
+
+ @Override
+ public int read() throws IOException {
+ return 0;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits16ToFromFloatArray.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2016, 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.util.Arrays;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioFormat.Encoding;
+
+import com.sun.media.sound.AudioFloatConverter;
+
+import static javax.sound.sampled.AudioFormat.Encoding.*;
+
+/**
+ * @test
+ * @bug 8152501
+ * @modules java.desktop/com.sun.media.sound
+ */
+public final class Bits16ToFromFloatArray {
+
+ private static final int SIZE = 16;
+
+ private static final float[] FLOATS = {-1.0f, 0, 1.0f};
+
+ private static short MID_U = (short) (Short.MAX_VALUE + 1);
+ private static short MAX_U = -1;
+
+ // BIG ENDIAN
+ private static final byte[] SIGNED_BIG = {
+ (byte) (Short.MIN_VALUE >> 8), (byte) (Short.MIN_VALUE & 0xff), 0,
+ 0, (byte) (Short.MAX_VALUE >> 8), (byte) (Short.MAX_VALUE & 0xff)
+ };
+
+ private static final byte[] UNSIGNED_BIG = {
+ 0, 0, (byte) (MID_U >> 8), (byte) (MID_U & 0xff),
+ (byte) (MAX_U >> 8), (byte) (MAX_U >> 8)
+ };
+
+ // LITTLE ENDIAN
+ private static final byte[] SIGNED_LITTLE = {
+ (byte) (Short.MIN_VALUE & 0xff), (byte) (Short.MIN_VALUE >> 8), 0,
+ 0, (byte) (Short.MAX_VALUE & 0xff), (byte) (Short.MAX_VALUE >> 8)
+ };
+
+ private static final byte[] UNSIGNED_LITTLE = {
+ 0, 0, (byte) (MID_U & 0xff), (byte) (MID_U >> 8),
+ (byte) (MAX_U >> 8), (byte) (MAX_U >> 8)
+ };
+
+ public static void main(final String[] args) {
+ test(PCM_UNSIGNED, UNSIGNED_BIG, true);
+ test(PCM_UNSIGNED, UNSIGNED_LITTLE, false);
+ test(PCM_SIGNED, SIGNED_LITTLE, false);
+ test(PCM_SIGNED, SIGNED_BIG, true);
+ }
+
+ private static void test(final Encoding enc, final byte[] expected,
+ boolean end) {
+ System.err.println("enc = " + enc);
+ AudioFormat af = new AudioFormat(enc, 44100, SIZE, 1, SIZE / 8, 44100,
+ end);
+ byte[] bytes = new byte[FLOATS.length * af.getFrameSize()];
+ AudioFloatConverter conv = AudioFloatConverter.getConverter(af);
+
+ conv.toByteArray(FLOATS, bytes);
+
+ if (!Arrays.equals(bytes, expected)) {
+ System.err.println("Actual: " + Arrays.toString(bytes));
+ System.err.println("Expected: " + Arrays.toString(expected));
+ throw new RuntimeException();
+ }
+
+ float[] floats = new float[bytes.length / af.getFrameSize()];
+ conv.toFloatArray(bytes, floats);
+
+ if (!Arrays.equals(floats, FLOATS)) {
+ System.err.println("Actual: " + Arrays.toString(floats));
+ System.err.println("Expected: " + Arrays.toString(FLOATS));
+ throw new RuntimeException();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits24ToFromFloatArray.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2016, 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.util.Arrays;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioFormat.Encoding;
+
+import com.sun.media.sound.AudioFloatConverter;
+
+import static javax.sound.sampled.AudioFormat.Encoding.PCM_SIGNED;
+import static javax.sound.sampled.AudioFormat.Encoding.PCM_UNSIGNED;
+
+/**
+ * @test
+ * @bug 8152501
+ * @modules java.desktop/com.sun.media.sound
+ */
+public final class Bits24ToFromFloatArray {
+
+ private static final int SIZE = 24;
+
+ private static final float[] FLOATS = {-1.0f, 0, 1.0f};
+
+ private static int MIN_S = -8_388_608;
+ private static int MAX_S = 8_388_607;
+
+ private static int MID_U = 0xFFFFFF / 2 + 1;
+ private static int MAX_U = 0xFFFFFF;
+
+ // BIG ENDIAN
+ private static final byte[] SIGNED_BIG = {
+ (byte) ((MIN_S >> 16) & 0xff),
+ (byte) ((MIN_S >> 8) & 0xff),
+ (byte) ((MIN_S >> 0) & 0xff),
+ 0, 0, 0,
+ (byte) ((MAX_S >> 16) & 0xff),
+ (byte) ((MAX_S >> 8) & 0xff),
+ (byte) ((MAX_S >> 0) & 0xff),
+ };
+
+ private static final byte[] UNSIGNED_BIG = {
+ 0, 0, 0,
+ (byte) ((MID_U >> 16) & 0xff),
+ (byte) ((MID_U >> 8) & 0xff),
+ (byte) ((MID_U >> 0) & 0xff),
+ (byte) ((MAX_U >> 16) & 0xff),
+ (byte) ((MAX_U >> 8) & 0xff),
+ (byte) ((MAX_U >> 0) & 0xff),
+
+ };
+
+ // LITTLE ENDIAN
+ private static final byte[] SIGNED_LITTLE = {
+ (byte) ((MIN_S >> 0) & 0xff),
+ (byte) ((MIN_S >> 8) & 0xff),
+ (byte) ((MIN_S >> 16) & 0xff),
+ 0, 0, 0,
+ (byte) ((MAX_S >> 0) & 0xff),
+ (byte) ((MAX_S >> 8) & 0xff),
+ (byte) ((MAX_S >> 16) & 0xff),
+ };
+
+ private static final byte[] UNSIGNED_LITTLE = {
+ 0, 0, 0,
+ (byte) ((MID_U >> 0) & 0xff),
+ (byte) ((MID_U >> 8) & 0xff),
+ (byte) ((MID_U >> 16) & 0xff),
+ (byte) ((MAX_U >> 0) & 0xff),
+ (byte) ((MAX_U >> 8) & 0xff),
+ (byte) ((MAX_U >> 16) & 0xff),
+ };
+
+ public static void main(final String[] args) {
+ test(PCM_UNSIGNED, UNSIGNED_BIG, true);
+ test(PCM_UNSIGNED, UNSIGNED_LITTLE, false);
+ test(PCM_SIGNED, SIGNED_LITTLE, false);
+ test(PCM_SIGNED, SIGNED_BIG, true);
+ }
+
+ private static void test(final Encoding enc, final byte[] expected,
+ boolean end) {
+ System.err.println(enc);
+ AudioFormat af = new AudioFormat(enc, 44100, SIZE, 1, SIZE / 8, 44100,
+ end);
+ byte[] bytes = new byte[FLOATS.length * af.getFrameSize()];
+ AudioFloatConverter conv = AudioFloatConverter.getConverter(af);
+
+ conv.toByteArray(FLOATS, bytes);
+
+ if (!Arrays.equals(bytes, expected)) {
+ System.err.println("Actual: " + Arrays.toString(bytes));
+ System.err.println("Expected: " + Arrays.toString(expected));
+ throw new RuntimeException();
+ }
+
+ float[] floats = new float[bytes.length / af.getFrameSize()];
+ conv.toFloatArray(bytes, floats);
+
+ if (!Arrays.equals(floats, FLOATS)) {
+ System.err.println("Actual: " + Arrays.toString(floats));
+ System.err.println("Expected: " + Arrays.toString(FLOATS));
+ throw new RuntimeException();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits32ToFromFloatArray.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2016, 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.util.Arrays;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioFormat.Encoding;
+
+import com.sun.media.sound.AudioFloatConverter;
+
+import static javax.sound.sampled.AudioFormat.Encoding.PCM_SIGNED;
+import static javax.sound.sampled.AudioFormat.Encoding.PCM_UNSIGNED;
+
+/**
+ * @test
+ * @bug 8152501
+ * @modules java.desktop/com.sun.media.sound
+ */
+public final class Bits32ToFromFloatArray {
+
+ private static final int SIZE = 32;
+
+ private static final float[] FLOATS = {-1.0f, 0, 1.0f};
+
+ private static int MID_U = (int) (Integer.MAX_VALUE + 1);
+ private static int MAX_U = -1;
+
+ // BIG ENDIAN
+ private static final byte[] SIGNED_BIG = {
+ (byte) ((Integer.MIN_VALUE >> 24) & 0xff),
+ (byte) ((Integer.MIN_VALUE >> 16) & 0xff),
+ (byte) ((Integer.MIN_VALUE >> 8) & 0xff),
+ (byte) ((Integer.MIN_VALUE >> 0) & 0xff),
+ 0, 0, 0, 0,
+ (byte) ((Integer.MAX_VALUE >> 24) & 0xff),
+ (byte) ((Integer.MAX_VALUE >> 16) & 0xff),
+ (byte) ((Integer.MAX_VALUE >> 8) & 0xff),
+ (byte) ((Integer.MAX_VALUE >> 0) & 0xff),
+ };
+
+ private static final byte[] UNSIGNED_BIG = {
+ 0, 0, 0, 0,
+ (byte) ((MID_U >> 24) & 0xff),
+ (byte) ((MID_U >> 16) & 0xff),
+ (byte) ((MID_U >> 8) & 0xff),
+ (byte) ((MID_U >> 0) & 0xff),
+ (byte) ((MAX_U >> 24) & 0xff),
+ (byte) ((MAX_U >> 16) & 0xff),
+ (byte) ((MAX_U >> 8) & 0xff),
+ (byte) ((MAX_U >> 0) & 0xff),
+
+ };
+
+ // LITTLE ENDIAN
+ private static final byte[] SIGNED_LITTLE = {
+ (byte) ((Integer.MIN_VALUE >> 0) & 0xff),
+ (byte) ((Integer.MIN_VALUE >> 8) & 0xff),
+ (byte) ((Integer.MIN_VALUE >> 16) & 0xff),
+ (byte) ((Integer.MIN_VALUE >> 24) & 0xff),
+ 0, 0, 0, 0,
+ (byte) ((Integer.MAX_VALUE >> 0) & 0xff),
+ (byte) ((Integer.MAX_VALUE >> 8) & 0xff),
+ (byte) ((Integer.MAX_VALUE >> 16) & 0xff),
+ (byte) ((Integer.MAX_VALUE >> 24) & 0xff),
+ };
+
+ private static final byte[] UNSIGNED_LITTLE = {
+ 0, 0, 0, 0,
+ (byte) ((MID_U >> 0) & 0xff),
+ (byte) ((MID_U >> 8) & 0xff),
+ (byte) ((MID_U >> 16) & 0xff),
+ (byte) ((MID_U >> 24) & 0xff),
+ (byte) ((MAX_U >> 0) & 0xff),
+ (byte) ((MAX_U >> 8) & 0xff),
+ (byte) ((MAX_U >> 16) & 0xff),
+ (byte) ((MAX_U >> 24) & 0xff),
+ };
+
+ public static void main(final String[] args) {
+ test(PCM_UNSIGNED, UNSIGNED_BIG, true);
+ test(PCM_UNSIGNED, UNSIGNED_LITTLE, false);
+ test(PCM_SIGNED, SIGNED_LITTLE, false);
+ test(PCM_SIGNED, SIGNED_BIG, true);
+ }
+
+ private static void test(final Encoding enc, final byte[] expected,
+ boolean end) {
+ AudioFormat af = new AudioFormat(enc, 44100, SIZE, 1, SIZE / 8, 44100,
+ end);
+ byte[] bytes = new byte[FLOATS.length * af.getFrameSize()];
+ AudioFloatConverter conv = AudioFloatConverter.getConverter(af);
+
+ conv.toByteArray(FLOATS, bytes);
+
+ if (!Arrays.equals(bytes, expected)) {
+ System.err.println("Actual: " + Arrays.toString(bytes));
+ System.err.println("Expected: " + Arrays.toString(expected));
+ throw new RuntimeException();
+ }
+
+ float[] floats = new float[bytes.length / af.getFrameSize()];
+ conv.toFloatArray(bytes, floats);
+
+ if (!Arrays.equals(floats, FLOATS)) {
+ System.err.println("Actual: " + Arrays.toString(floats));
+ System.err.println("Expected: " + Arrays.toString(FLOATS));
+ throw new RuntimeException();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits64ToFromFloatArray.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2016, 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.util.Arrays;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioFormat.Encoding;
+
+import com.sun.media.sound.AudioFloatConverter;
+
+import static javax.sound.sampled.AudioFormat.Encoding.PCM_SIGNED;
+import static javax.sound.sampled.AudioFormat.Encoding.PCM_UNSIGNED;
+
+/**
+ * @test
+ * @bug 8152501
+ * @modules java.desktop/com.sun.media.sound
+ */
+public final class Bits64ToFromFloatArray {
+
+ private static final int SIZE = 64;
+
+ private static final float[] FLOATS = {-1.0f, 0, 1.0f};
+
+ private static long MID_U = (long) (Long.MAX_VALUE + 1);
+ private static long MAX_U = -1;
+
+ // BIG ENDIAN
+ private static final byte[] SIGNED_BIG = {
+ (byte) ((Long.MIN_VALUE >> 56) & 0xff),
+ (byte) ((Long.MIN_VALUE >> 48) & 0xff),
+ (byte) ((Long.MIN_VALUE >> 40) & 0xff),
+ (byte) ((Long.MIN_VALUE >> 32) & 0xff),
+ 0, 0, 0, 0, // current javasound impl will ignore this
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ (byte) ((Long.MAX_VALUE >> 56) & 0xff),
+ (byte) ((Long.MAX_VALUE >> 48) & 0xff),
+ (byte) ((Long.MAX_VALUE >> 40) & 0xff),
+ (byte) ((Long.MAX_VALUE >> 32) & 0xff),
+ 0, 0, 0, 0, // current javasound impl will ignore this
+ };
+
+ private static final byte[] UNSIGNED_BIG = {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ (byte) ((MID_U >> 56) & 0xff),
+ (byte) ((MID_U >> 48) & 0xff),
+ (byte) ((MID_U >> 40) & 0xff),
+ (byte) ((MID_U >> 32) & 0xff),
+ 0, 0, 0, 0, // current javasound impl will ignore this
+ (byte) ((MAX_U >> 56) & 0xff),
+ (byte) ((MAX_U >> 48) & 0xff),
+ (byte) ((MAX_U >> 40) & 0xff),
+ (byte) ((MAX_U >> 32) & 0xff),
+ 0, 0, 0, 0, // current javasound impl will ignore this
+ };
+
+ // LITTLE ENDIAN
+ private static final byte[] SIGNED_LITTLE = {
+ 0, 0, 0, 0, // current javasound impl will ignore this
+ (byte) ((Long.MIN_VALUE >> 32) & 0xff),
+ (byte) ((Long.MIN_VALUE >> 40) & 0xff),
+ (byte) ((Long.MIN_VALUE >> 48) & 0xff),
+ (byte) ((Long.MIN_VALUE >> 56) & 0xff),
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0, // current javasound impl will ignore this
+ (byte) ((Long.MAX_VALUE >> 32) & 0xff),
+ (byte) ((Long.MAX_VALUE >> 40) & 0xff),
+ (byte) ((Long.MAX_VALUE >> 48) & 0xff),
+ (byte) ((Long.MAX_VALUE >> 56) & 0xff),
+ };
+
+ private static final byte[] UNSIGNED_LITTLE = {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0, // current javasound impl will ignore this
+ (byte) ((MID_U >> 32) & 0xff),
+ (byte) ((MID_U >> 40) & 0xff),
+ (byte) ((MID_U >> 48) & 0xff),
+ (byte) ((MID_U >> 56) & 0xff),
+ 0, 0, 0, 0, // current javasound impl will ignore this
+ (byte) ((MAX_U >> 32) & 0xff),
+ (byte) ((MAX_U >> 40) & 0xff),
+ (byte) ((MAX_U >> 48) & 0xff),
+ (byte) ((MAX_U >> 56) & 0xff),
+ };
+
+ public static void main(final String[] args) {
+ test(PCM_UNSIGNED, UNSIGNED_BIG, true);
+ test(PCM_UNSIGNED, UNSIGNED_LITTLE, false);
+ test(PCM_SIGNED, SIGNED_LITTLE, false);
+ test(PCM_SIGNED, SIGNED_BIG, true);
+ }
+
+ private static void test(final Encoding enc, final byte[] expected,
+ boolean end) {
+ System.err.println(enc);
+ AudioFormat af = new AudioFormat(enc, 44100, SIZE, 1, SIZE / 8, 44100,
+ end);
+ byte[] bytes = new byte[FLOATS.length * af.getFrameSize()];
+ AudioFloatConverter conv = AudioFloatConverter.getConverter(af);
+
+ conv.toByteArray(FLOATS, bytes);
+
+ if (!Arrays.equals(bytes, expected)) {
+ System.err.println("Actual: " + Arrays.toString(bytes));
+ System.err.println("Expected: " + Arrays.toString(expected));
+ throw new RuntimeException();
+ }
+
+ float[] floats = new float[bytes.length / af.getFrameSize()];
+ conv.toFloatArray(bytes, floats);
+
+ if (!Arrays.equals(floats, FLOATS)) {
+ System.err.println("Actual: " + Arrays.toString(floats));
+ System.err.println("Expected: " + Arrays.toString(FLOATS));
+ throw new RuntimeException();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits8ToFromFloatArray.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2016, 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.util.Arrays;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioFormat.Encoding;
+
+import com.sun.media.sound.AudioFloatConverter;
+
+import static javax.sound.sampled.AudioFormat.Encoding.*;
+
+/**
+ * @test
+ * @bug 8152501
+ * @modules java.desktop/com.sun.media.sound
+ */
+public final class Bits8ToFromFloatArray {
+
+ private static final int SIZE = 8;
+
+ private static final float[] FLOATS = {-1.0f, 0, 1.0f};
+
+ private static final byte[] SIGNED = {Byte.MIN_VALUE, 0, Byte.MAX_VALUE};
+
+ private static final byte[] UNSIGNED = {
+ 0, (byte) (Byte.MAX_VALUE + 1), (byte) -1
+ };
+
+ public static void main(final String[] args) {
+ test(PCM_UNSIGNED, UNSIGNED);
+ test(PCM_SIGNED, SIGNED);
+ }
+
+ private static void test(final Encoding enc, final byte[] expected) {
+ AudioFormat af = new AudioFormat(enc, 44100, SIZE, 1, SIZE / 8, 44100,
+ true);
+ byte[] bytes = new byte[FLOATS.length * af.getFrameSize()];
+ AudioFloatConverter conv = AudioFloatConverter.getConverter(af);
+
+ conv.toByteArray(FLOATS, bytes);
+
+ if (!Arrays.equals(bytes, expected)) {
+ System.err.println("Actual: " + Arrays.toString(bytes));
+ System.err.println("Expected: " + Arrays.toString(expected));
+ throw new RuntimeException();
+ }
+
+ float[] floats = new float[bytes.length / af.getFrameSize()];
+ conv.toFloatArray(bytes, floats);
+
+ if (!Arrays.equals(floats, FLOATS)) {
+ System.err.println("Actual: " + Arrays.toString(floats));
+ System.err.println("Expected: " + Arrays.toString(FLOATS));
+ throw new RuntimeException();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JFileChooser/DeserializedJFileChooser/DeserializedJFileChooserTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2016, 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 8146301
+ * @summary Enter key does not work in a deserialized JFileChooser.
+ * @run main DeserializedJFileChooserTest
+ */
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.KeyEvent;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+public class DeserializedJFileChooserTest {
+
+ private static int state = -1;
+ private static JFileChooser deserialized;
+
+ public static void main(String[] args) throws Exception {
+ SwingUtilities.invokeLater( () -> {
+ try {
+ JFileChooser jfc = new JFileChooser();
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(bos);
+ oos.writeObject(jfc);
+ oos.close();
+ ByteArrayInputStream bis =
+ new ByteArrayInputStream(bos.toByteArray());
+ ObjectInputStream ois = new ObjectInputStream(bis);
+ deserialized = (JFileChooser) ois.readObject();
+ state = deserialized.showOpenDialog(null);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ });
+ Robot robot = new Robot();
+ robot.setAutoDelay(50);
+ robot.waitForIdle();
+ robot.keyPress(KeyEvent.VK_A);
+ robot.keyRelease(KeyEvent.VK_A);
+ robot.keyPress(KeyEvent.VK_ENTER);
+ robot.keyRelease(KeyEvent.VK_ENTER);
+ robot.waitForIdle();
+ robot.delay(1000);
+ if (state != JFileChooser.APPROVE_OPTION) {
+ deserialized.cancelSelection();
+ throw new RuntimeException("Failed");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JInternalFrame/DockIconRepaint/DockIconRepaint.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2016, 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.awt.Color;
+import java.awt.EventQueue;
+import java.awt.Graphics;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Robot;
+import java.beans.PropertyVetoException;
+
+import javax.swing.JDesktopPane;
+import javax.swing.JFrame;
+import javax.swing.JInternalFrame;
+import javax.swing.JPanel;
+
+/**
+ * @test
+ * @bug 8144166
+ * @requires (os.family == "mac")
+ */
+public final class DockIconRepaint {
+
+ private static volatile Color color;
+
+ private static JFrame frame;
+
+ private static JInternalFrame jif;
+
+ private static Robot robot;
+
+ private static Point iconLoc;
+
+ private static Rectangle iconBounds;
+
+ public static void main(final String[] args) throws Exception {
+ robot = new Robot();
+ EventQueue.invokeAndWait(DockIconRepaint::createUI);
+ try {
+ robot.waitForIdle();
+ color = Color.BLUE;
+ test();
+ color = Color.RED;
+ test();
+ color = Color.GREEN;
+ test();
+ } finally {
+ frame.dispose();
+ }
+ }
+
+ private static void test() throws Exception {
+ // maximize the frame to force repaint
+ EventQueue.invokeAndWait(() -> {
+ try {
+ jif.setIcon(false);
+ jif.setMaximum(true);
+ } catch (PropertyVetoException e) {
+ throw new RuntimeException(e);
+ }
+ });
+ robot.waitForIdle();
+ Thread.sleep(1000);
+ // minimize the frame to dock, the icon should be up2date
+ EventQueue.invokeAndWait(() -> {
+ try {
+ jif.setIcon(true);
+ } catch (PropertyVetoException e) {
+ throw new RuntimeException(e);
+ }
+ iconLoc = jif.getDesktopIcon().getLocationOnScreen();
+ iconBounds = jif.getDesktopIcon().getBounds();
+ });
+ robot.waitForIdle();
+ Thread.sleep(1000);
+
+ final Color c = robot.getPixelColor(iconLoc.x + iconBounds.width / 2,
+ iconLoc.y + iconBounds.height / 2);
+ if (c.getRGB() != color.getRGB()) {
+ System.err.println("Exp: " + Integer.toHexString(color.getRGB()));
+ System.err.println("Actual: " + Integer.toHexString(c.getRGB()));
+ throw new RuntimeException("Wrong color.");
+ }
+ }
+
+ private static void createUI() {
+ frame = new JFrame();
+ frame.setUndecorated(true);
+ frame.setSize(300, 300);
+ frame.setLocationRelativeTo(null);
+ final JDesktopPane pane = new JDesktopPane();
+ final JPanel panel = new JPanel() {
+ @Override
+ protected void paintComponent(Graphics g) {
+ g.setColor(color);
+ g.fillRect(0, 0, getWidth(), getHeight());
+ }
+ };
+ jif = new JInternalFrame();
+ jif.add(panel);
+ jif.setVisible(true);
+ jif.setSize(300, 300);
+ pane.add(jif);
+ frame.add(pane);
+ frame.setVisible(true);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JPopupMenu/6949414/JPopupMenuEndlessLoopTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016, 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 javax.swing.JMenu;
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+import javax.swing.MenuElement;
+import javax.swing.MenuSelectionManager;
+import javax.swing.SwingUtilities;
+
+/**
+ * @test
+ * @bug 6949414 6424606
+ * @summary JMenu.buildMenuElementArray() endless loop
+ * @run main/timeout=5 JPopupMenuEndlessLoopTest
+ */
+public class JPopupMenuEndlessLoopTest {
+
+ public static void main(String[] args) throws Exception {
+ SwingUtilities.invokeAndWait(() -> {
+
+ JPopupMenu popup = new JPopupMenu("Popup Menu");
+ JMenu menu = new JMenu("Menu");
+ menu.add(new JMenuItem("Menu Item"));
+ popup.add(menu);
+ menu.doClick();
+ MenuElement[] elems = MenuSelectionManager
+ .defaultManager().getSelectedPath();
+
+ if (elems == null || elems.length == 0) {
+ throw new RuntimeException("Empty Selection");
+ }
+
+ if (elems[0] != popup || elems[1] != menu) {
+ throw new RuntimeException("Necessary menus are not selected!");
+ }
+ });
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JTabbedPane/8137169/ScrollableTabbedPaneTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2016, 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 8137169
+ * @summary verifies TabbedScrollPane minimum height for all Look and Feels
+ * @library ../../regtesthelpers
+ * @build Util
+ * @run main ScrollableTabbedPaneTest
+ */
+
+import java.awt.Robot;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JTabbedPane;
+import javax.swing.SwingConstants;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.UnsupportedLookAndFeelException;
+
+public class ScrollableTabbedPaneTest {
+
+ private static JFrame frame;
+ private static JTabbedPane pane;
+ private static Robot robot;
+ private static volatile String errorString = "";
+
+ public static void main(String[] args) throws Exception {
+ robot = new Robot();
+ robot.delay(1000);
+ UIManager.LookAndFeelInfo[] lookAndFeelArray
+ = UIManager.getInstalledLookAndFeels();
+ for (UIManager.LookAndFeelInfo lookAndFeelItem : lookAndFeelArray) {
+ executeCase(lookAndFeelItem.getClassName(),
+ lookAndFeelItem.getName());
+ }
+ if (!"".equals(errorString)) {
+ throw new RuntimeException("Error Log:\n" + errorString);
+ }
+ }
+
+ private static void executeCase(String lookAndFeelString, String shortLAF)
+ throws Exception {
+ if (tryLookAndFeel(lookAndFeelString)) {
+ createUI(shortLAF);
+ stepsToExecute(shortLAF);
+
+ createLeftUI(shortLAF);
+ stepsToExecute(shortLAF);
+
+ createRightUI(shortLAF);
+ stepsToExecute(shortLAF);
+ }
+ }
+
+ private static void stepsToExecute(String shortLAF) throws Exception {
+ robot.delay(100);
+ runTestCase(shortLAF);
+ robot.delay(1000);
+ cleanUp();
+ robot.delay(1000);
+ }
+
+ private static boolean tryLookAndFeel(String lookAndFeelString)
+ throws Exception {
+ try {
+ UIManager.setLookAndFeel(
+ lookAndFeelString);
+
+ } catch (UnsupportedLookAndFeelException
+ | ClassNotFoundException
+ | InstantiationException
+ | IllegalAccessException e) {
+ return false;
+ }
+ return true;
+ }
+
+ private static void cleanUp() throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ frame.dispose();
+ }
+ });
+ }
+
+ private static void createUI(final String shortLAF)
+ throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ frame = new JFrame(shortLAF);
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frame.setVisible(true);
+ pane = new JTabbedPane();
+ pane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
+ frame.add(pane);
+ frame.setSize(500, 500);
+ }
+ });
+ }
+ private static void createLeftUI(final String shortLAF)
+ throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ frame = new JFrame(shortLAF);
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frame.setVisible(true);
+ pane = new JTabbedPane();
+ pane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
+ pane.setTabPlacement(SwingConstants.LEFT);
+ frame.add(pane);
+ frame.setSize(500, 500);
+ }
+ });
+ }
+
+ private static void createRightUI(final String shortLAF)
+ throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ frame = new JFrame(shortLAF);
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frame.setVisible(true);
+ pane = new JTabbedPane();
+ pane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
+ pane.setTabPlacement(SwingConstants.RIGHT);
+ frame.add(pane);
+ frame.setSize(500, 500);
+ }
+ });
+ }
+
+ private static void runTestCase(String shortLAF) throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ int i = 0;
+ int value= 0;
+ do {
+ String title = "Tab" + (i + 1);
+ pane.addTab(title, new JPanel());
+ int tempValue = pane.getMinimumSize().height;
+ if(value==0) {
+ value = tempValue;
+ }
+ if(value != tempValue) {
+ String error = "[" + shortLAF
+ + "]: [Error]: TabbedScrollPane fails";
+ errorString += error;
+ }
+
+ ++i;
+ } while (i < 10);
+ }
+ });
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/LookAndFeel/6897701/JMenuItemsTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2016, 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 6897701
+ * @summary Verify JMenu and JMenuItem Disabled state for Nimbus LAF
+ * @run main JMenuItemsTest
+ */
+import java.awt.Color;
+import java.awt.Rectangle;
+import java.awt.image.BufferedImage;
+import javax.swing.JFrame;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+
+public class JMenuItemsTest {
+
+ private static JFrame mainFrame;
+ private static JMenu disabledMenu;
+ private static JMenuItem disabledMenuItem;
+
+ public JMenuItemsTest() {
+ createUI();
+ }
+
+ private void createUI() {
+
+ mainFrame = new JFrame("Test");
+
+ disabledMenu = new JMenu("Disabled Menu");
+ disabledMenu.setForeground(Color.BLUE);
+ disabledMenu.setEnabled(false);
+
+ disabledMenuItem = new JMenuItem("Disabled MenuItem");
+ disabledMenuItem.setForeground(Color.BLUE);
+ disabledMenuItem.setEnabled(false);
+
+ JMenuBar menuBar = new JMenuBar();
+ menuBar = new JMenuBar();
+ menuBar.add(disabledMenu);
+ menuBar.add(disabledMenuItem);
+
+ mainFrame.add(menuBar);
+ mainFrame.pack();
+ mainFrame.setVisible(true);
+ }
+
+ private void dispose() {
+ mainFrame.dispose();
+ }
+
+ private void testDisabledStateOfJMenu() {
+
+ // Test disabled JMenu state
+ Rectangle rect = disabledMenu.getBounds();
+ BufferedImage image = new BufferedImage(rect.width, rect.height,
+ BufferedImage.TYPE_INT_ARGB);
+ disabledMenu.paint(image.getGraphics());
+ int y = image.getHeight() / 2;
+ for (int x = 0; x < image.getWidth(); x++) {
+ Color c = new Color(image.getRGB(x, y));
+ if (c.equals(Color.BLUE)) {
+ dispose();
+ throw new RuntimeException("JMenu Disabled"
+ + " State not Valid.");
+ }
+ }
+
+ }
+
+ private void testDisabledStateOfJMenuItem() {
+
+ // Test disabled JMenuItem state
+ Rectangle rect = disabledMenuItem.getBounds();
+ BufferedImage image = new BufferedImage(rect.width, rect.height,
+ BufferedImage.TYPE_INT_ARGB);
+ disabledMenuItem.paint(image.getGraphics());
+ int y = image.getHeight() / 2;
+ for (int x = 0; x < image.getWidth(); x++) {
+ Color c = new Color(image.getRGB(x, y));
+ if (c.equals(Color.BLUE)) {
+ dispose();
+ throw new RuntimeException("JMenuItem Disabled"
+ + " State not Valid.");
+ }
+ }
+
+ }
+
+ public static void main(String[] args) throws Exception {
+ UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
+ SwingUtilities.invokeAndWait(() -> {
+
+ try {
+ JMenuItemsTest obj = new JMenuItemsTest();
+ obj.testDisabledStateOfJMenu();
+ obj.testDisabledStateOfJMenuItem();
+ obj.dispose();
+
+ } catch (Exception ex) {
+ throw ex;
+ }
+
+ });
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/text/html/CSS/ColorValue/RGBColorValueTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 1998, 2016, 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.
+ */
+
+/*
+ * @test
+ * @bug 8149631
+ * @summary rgb(...) CSS color values are not parsed properly
+ * @run main RGBColorValueTest
+ */
+
+import javax.swing.text.AttributeSet;
+import javax.swing.text.html.StyleSheet;
+
+import static javax.swing.text.html.CSS.Attribute.*;
+
+public class RGBColorValueTest {
+
+ public static void main(String[] args) {
+ StyleSheet styleSheet = new StyleSheet();
+ AttributeSet attributeSet = styleSheet.
+ getDeclaration("border-color: rgb(1, 2, 3) rgb(1, 2, 4);");
+ if (!attributeSet.getAttribute(BORDER_TOP_COLOR).toString()
+ .equals("rgb(1, 2, 3)") ||
+ !attributeSet.getAttribute(BORDER_BOTTOM_COLOR).toString()
+ .equals("rgb(1, 2, 3)") ||
+ !attributeSet.getAttribute(BORDER_RIGHT_COLOR).toString()
+ .equals("rgb(1, 2, 4)") ||
+ !attributeSet.getAttribute(BORDER_LEFT_COLOR).toString()
+ .equals("rgb(1, 2, 4)") ) {
+ throw new RuntimeException("Failed");
+ }
+ }
+}
--- a/jdk/test/jdk/internal/jrtfs/WithSecurityManager.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/jdk/internal/jrtfs/WithSecurityManager.java Thu Apr 21 13:37:31 2016 -0700
@@ -31,6 +31,7 @@
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.Collections;
public class WithSecurityManager {
public static void main(String[] args) throws Exception {
@@ -61,7 +62,7 @@
// check FileSystems.newFileSystem
try {
- FileSystems.newFileSystem(URI.create("jrt:/"), null);
+ FileSystems.newFileSystem(URI.create("jrt:/"), Collections.emptyMap());
if (!allow) throw new RuntimeException("access not expected");
} catch (SecurityException se) {
if (allow)
--- a/jdk/test/jdk/internal/jrtfs/remote/Main.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/jdk/internal/jrtfs/remote/Main.java Thu Apr 21 13:37:31 2016 -0700
@@ -30,6 +30,7 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.Collections;
import java.util.stream.Stream;
/**
@@ -69,11 +70,12 @@
private static FileSystem createFsWithURLClassloader(String javaHome) throws IOException{
URL url = Paths.get(javaHome, "jrt-fs.jar").toUri().toURL();
URLClassLoader loader = new URLClassLoader(new URL[] { url });
- return FileSystems.newFileSystem(URI.create("jrt:/"), null, loader);
+ return FileSystems.newFileSystem(URI.create("jrt:/"),
+ Collections.emptyMap(),
+ loader);
}
private static FileSystem createFsByInstalledProvider() throws IOException {
return FileSystems.getFileSystem(URI.create("jrt:/"));
}
}
-
--- a/jdk/test/jdk/internal/jrtfs/remote/RemoteRuntimeImageTest.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/jdk/internal/jrtfs/remote/RemoteRuntimeImageTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8141609
+ * @bug 8141609 8154403
* @summary Verify JDK 8 can use jrt-fs.jar to work with jrt file system.
* @run main RemoteRuntimeImageTest
*/
@@ -63,7 +63,6 @@
String java = jdk8Path.resolve("bin/java").toAbsolutePath().toString();
String javac = jdk8Path.resolve("bin/javac").toAbsolutePath().toString();
-
Files.createDirectories(Paths.get(".", CLASSES_DIR));
String jrtJar = Paths.get(TEST_JAVAHOME, JRTFS_JAR).toAbsolutePath().toString();
@@ -121,4 +120,3 @@
return version.startsWith("\"1.8");
}
}
-
--- a/jdk/test/sanity/client/lib/SwingSet3/README Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/sanity/client/lib/SwingSet3/README Thu Apr 21 13:37:31 2016 -0700
@@ -1,4 +1,4 @@
This content of this src folder was originally taken from SwingSet3 demo project: https://java.net/projects/swingset3/.
Then it was modified to increase testability and remove extra content and extra dependencies.
-Do NOT modify files in it.
\ No newline at end of file
+This is NOT the official location of the SwingSet3 demo.
\ No newline at end of file
--- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/button/ButtonDemo.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/button/ButtonDemo.java Thu Apr 21 13:37:31 2016 -0700
@@ -215,7 +215,6 @@
javax.swing.SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame(DEMO_TITLE);
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(buttonDemo);
frame.pack();
frame.setVisible(true);
--- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/combobox/ComboBoxDemo.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/combobox/ComboBoxDemo.java Thu Apr 21 13:37:31 2016 -0700
@@ -120,7 +120,6 @@
public static void main(String[] args) {
JFrame frame = new JFrame(DEMO_TITLE);
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new ComboBoxDemo());
frame.setPreferredSize(new Dimension(800, 600));
frame.pack();
--- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/list/ListDemo.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/list/ListDemo.java Thu Apr 21 13:37:31 2016 -0700
@@ -90,7 +90,6 @@
public static void main(String[] args) {
JFrame frame = new JFrame(DEMO_TITLE);
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new ListDemo());
frame.setPreferredSize(new Dimension(800, 600));
frame.pack();
--- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/optionpane/OptionPaneDemo.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/optionpane/OptionPaneDemo.java Thu Apr 21 13:37:31 2016 -0700
@@ -93,7 +93,6 @@
public static void main(String[] args) {
JFrame frame = new JFrame(DEMO_TITLE);
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new OptionPaneDemo());
frame.setPreferredSize(new Dimension(800, 600));
frame.pack();
--- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/progressbar/ProgressBarDemo.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/progressbar/ProgressBarDemo.java Thu Apr 21 13:37:31 2016 -0700
@@ -64,7 +64,6 @@
public static void main(String[] args) {
JFrame frame = new JFrame(DEMO_TITLE);
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new ProgressBarDemo());
frame.setPreferredSize(new Dimension(800, 600));
frame.pack();
--- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/scrollpane/ScrollPaneDemo.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/scrollpane/ScrollPaneDemo.java Thu Apr 21 13:37:31 2016 -0700
@@ -64,7 +64,6 @@
public static void main(String[] args) {
JFrame frame = new JFrame(DEMO_TITLE);
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new ScrollPaneDemo());
frame.setPreferredSize(new Dimension(800, 600));
frame.pack();
--- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/spinner/SpinnerDemo.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/spinner/SpinnerDemo.java Thu Apr 21 13:37:31 2016 -0700
@@ -58,7 +58,6 @@
public static void main(String[] args) {
JFrame frame = new JFrame(DEMO_TITLE);
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new SpinnerDemo());
frame.setPreferredSize(new Dimension(800, 600));
frame.pack();
--- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/splitpane/SplitPaneDemo.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/splitpane/SplitPaneDemo.java Thu Apr 21 13:37:31 2016 -0700
@@ -86,7 +86,6 @@
public static void main(String[] args) {
JFrame frame = new JFrame(DEMO_TITLE);
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new SplitPaneDemo());
frame.setPreferredSize(new Dimension(800, 600));
frame.pack();
--- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/textfield/TextFieldDemo.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/textfield/TextFieldDemo.java Thu Apr 21 13:37:31 2016 -0700
@@ -115,7 +115,6 @@
public static void main(String[] args) {
JFrame frame = new JFrame(DEMO_TITLE);
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new TextFieldDemo());
frame.setPreferredSize(new Dimension(800, 600));
frame.pack();
--- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/togglebutton/ToggleButtonDemo.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/togglebutton/ToggleButtonDemo.java Thu Apr 21 13:37:31 2016 -0700
@@ -151,7 +151,6 @@
public static void main(String[] args) {
JFrame frame = new JFrame(ToggleButtonDemo.class.getAnnotation(DemoProperties.class).value());
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new ToggleButtonDemo());
frame.setPreferredSize(new Dimension(800, 600));
frame.pack();
--- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tree/TreeDemo.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tree/TreeDemo.java Thu Apr 21 13:37:31 2016 -0700
@@ -65,7 +65,6 @@
public static void main(String[] args) {
JFrame frame = new JFrame(DEMO_TITLE);
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new TreeDemo());
frame.setPreferredSize(new Dimension(800, 600));
frame.pack();
--- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/window/WindowDemo.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/window/WindowDemo.java Thu Apr 21 13:37:31 2016 -0700
@@ -150,7 +150,6 @@
JFrame frame = new JFrame();
WindowDemo demo = new WindowDemo();
frame.add(demo);
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
demo.start();
--- a/jdk/test/sun/security/provider/DSA/TestDSA2.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/sun/security/provider/DSA/TestDSA2.java Thu Apr 21 13:37:31 2016 -0700
@@ -60,8 +60,8 @@
boolean[] expectedToPass = { true, true, true, true,
true, true, true, true };
test(1024, expectedToPass);
- boolean[] expectedToPass2 = { true, true, true, true,
- true, true, true, true };
+ boolean[] expectedToPass2 = { true, false, true, true,
+ true, false, true, true };
test(2048, expectedToPass2);
}
--- a/jdk/test/sun/security/rsa/SpecTest.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/sun/security/rsa/SpecTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -20,32 +20,32 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
+/**
+ * @test
+ * @bug 8044199 8137231
+ * @key intermittent
+ * @summary Check same KeyPair's private key and public key have same modulus.
+ * also check public key's public exponent equals to given spec's public
+ * exponent. Only key size 1024 is tested with RSAKeyGenParameterSpec.F0 (3).
+ * @run main SpecTest 512
+ * @run main SpecTest 768
+ * @run main SpecTest 1024
+ * @run main SpecTest 1024 3
+ * @run main SpecTest 2048
+ * @run main/timeout=240 SpecTest 4096
+ * @run main/timeout=240 SpecTest 5120
+ */
import java.math.BigInteger;
-import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
import java.security.interfaces.RSAKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAKeyGenParameterSpec;
-/**
- * @test
- * @bug 8044199
- * @key intermittent
- * @summary Check same KeyPair's private key and public key have same modulus.
- * also check public key's public exponent equals to given spec's public
- * exponent.
- * @run main SpecTest 512
- * @run main SpecTest 768
- * @run main SpecTest 1024
- * @run main SpecTest 2048
- * @run main/timeout=240 SpecTest 4096
- * @run main/timeout=240 SpecTest 5120
- */
public class SpecTest {
+
/**
* ALGORITHM name, fixed as RSA.
*/
@@ -70,14 +70,14 @@
// test the getModulus method
if ((priv instanceof RSAKey) && (pub instanceof RSAKey)) {
if (!priv.getModulus().equals(pub.getModulus())) {
- System.err.println("priv.getModulus() = " + priv.getModulus());
- System.err.println("pub.getModulus() = " + pub.getModulus());
+ System.out.println("priv.getModulus() = " + priv.getModulus());
+ System.out.println("pub.getModulus() = " + pub.getModulus());
passed = false;
}
if (!pubExponent.equals(pub.getPublicExponent())) {
- System.err.println("pubExponent = " + pubExponent);
- System.err.println("pub.getPublicExponent() = "
+ System.out.println("pubExponent = " + pubExponent);
+ System.out.println("pub.getPublicExponent() = "
+ pub.getPublicExponent());
passed = false;
}
@@ -85,36 +85,26 @@
return passed;
}
- public static void main(String[] args) {
- int failCount = 0;
+ public static void main(String[] args) throws Exception {
- // Test key size.
- int size = Integer.parseInt(args[0]);
+ int size = 0;
- try {
- KeyPairGenerator kpg1 = KeyPairGenerator.getInstance(KEYALG, PROVIDER);
- kpg1.initialize(new RSAKeyGenParameterSpec(size,
- RSAKeyGenParameterSpec.F4));
- if (!specTest(kpg1.generateKeyPair(),
- RSAKeyGenParameterSpec.F4)) {
- failCount++;
- }
-
- KeyPairGenerator kpg2 = KeyPairGenerator.getInstance(KEYALG, PROVIDER);
- kpg2.initialize(new RSAKeyGenParameterSpec(size,
- RSAKeyGenParameterSpec.F0));
- if (!specTest(kpg2.generateKeyPair(), RSAKeyGenParameterSpec.F0)) {
- failCount++;
- }
- } catch (NoSuchAlgorithmException | NoSuchProviderException
- | InvalidAlgorithmParameterException ex) {
- ex.printStackTrace(System.err);
- failCount++;
+ if (args.length >= 1) {
+ size = Integer.parseInt(args[0]);
+ } else {
+ throw new RuntimeException("Missing keysize to test with");
}
- if (failCount != 0) {
- throw new RuntimeException("There are " + failCount
- + " tests failed.");
+ BigInteger publicExponent
+ = (args.length >= 2) ? new BigInteger(args[1]) : RSAKeyGenParameterSpec.F4;
+
+ System.out.println("Running test with key size: " + size
+ + " and public exponent: " + publicExponent);
+
+ KeyPairGenerator kpg1 = KeyPairGenerator.getInstance(KEYALG, PROVIDER);
+ kpg1.initialize(new RSAKeyGenParameterSpec(size, publicExponent));
+ if (!specTest(kpg1.generateKeyPair(), publicExponent)) {
+ throw new RuntimeException("Test failed.");
}
}
}
--- a/jdk/test/sun/security/ssl/SSLContextImpl/MD2InTrustAnchor.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/sun/security/ssl/SSLContextImpl/MD2InTrustAnchor.java Thu Apr 21 13:37:31 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, 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
@@ -37,106 +37,88 @@
* @run main/othervm MD2InTrustAnchor PKIX TLSv1.2
* @run main/othervm MD2InTrustAnchor SunX509 TLSv1.2
*/
-
-import java.net.*;
-import java.util.*;
-import java.io.*;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
import javax.net.ssl.*;
import java.security.Security;
import java.security.KeyStore;
import java.security.KeyFactory;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
-import java.security.spec.*;
-import java.security.interfaces.*;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
+import java.util.concurrent.CountDownLatch;
public class MD2InTrustAnchor {
/*
- * =============================================================
- * Set the various variables needed for the tests, then
- * specify what tests to run on each side.
- */
-
- /*
- * Should we run the client or server in a separate thread?
- * Both sides can throw exceptions, but do you have a preference
- * as to which side should be the main thread.
- */
- static boolean separateServerThread = false;
-
- /*
* Certificates and key used in the test.
*/
-
// It's a trust anchor signed with MD2 hash function.
- static String trustedCertStr =
- "-----BEGIN CERTIFICATE-----\n" +
- "MIICkjCCAfugAwIBAgIBADANBgkqhkiG9w0BAQIFADA7MQswCQYDVQQGEwJVUzEN\n" +
- "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" +
- "MTExMTE4MTExNDA0WhcNMzIxMDI4MTExNDA0WjA7MQswCQYDVQQGEwJVUzENMAsG\n" +
- "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwgZ8wDQYJ\n" +
- "KoZIhvcNAQEBBQADgY0AMIGJAoGBAPGyB9tugUGgxtdeqe0qJEwf9x1Gy4BOi1yR\n" +
- "wzDZY4H5LquvIfQ2V3J9X1MQENVsFvkvp65ZcFcy+ObOucXUUPFcd/iw2DVb5QXA\n" +
- "ffyeVqWD56GPi8Qe37wrJO3L6fBhN9oxp/BbdRLgjU81zx8qLEyPODhPMxV4OkcA\n" +
- "SDwZTSxxAgMBAAGjgaUwgaIwHQYDVR0OBBYEFLOAtr/YrYj9H04EDLA0fd14jisF\n" +
- "MGMGA1UdIwRcMFqAFLOAtr/YrYj9H04EDLA0fd14jisFoT+kPTA7MQswCQYDVQQG\n" +
- "EwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2\n" +
- "Y2WCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEC\n" +
- "BQADgYEAr8ExpXu/FTIRiMzPm0ubqwME4lniilwQUiEOD/4DbksNjEIcUyS2hIk1\n" +
- "qsmjJz3SHBnwhxl9dhJVwk2tZLkPGW86Zn0TPVRsttK4inTgCC9GFGeqQBdrU/uf\n" +
- "lipBzXWljrfbg4N/kK8m2LabtKUMMnGysM8rN0Fx2PYm5xxGvtM=\n" +
- "-----END CERTIFICATE-----";
+ private static final String TRUSTED_CERT_STR = "-----BEGIN CERTIFICATE-----\n"
+ + "MIICkjCCAfugAwIBAgIBADANBgkqhkiG9w0BAQIFADA7MQswCQYDVQQGEwJVUzEN\n"
+ + "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n"
+ + "MTExMTE4MTExNDA0WhcNMzIxMDI4MTExNDA0WjA7MQswCQYDVQQGEwJVUzENMAsG\n"
+ + "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwgZ8wDQYJ\n"
+ + "KoZIhvcNAQEBBQADgY0AMIGJAoGBAPGyB9tugUGgxtdeqe0qJEwf9x1Gy4BOi1yR\n"
+ + "wzDZY4H5LquvIfQ2V3J9X1MQENVsFvkvp65ZcFcy+ObOucXUUPFcd/iw2DVb5QXA\n"
+ + "ffyeVqWD56GPi8Qe37wrJO3L6fBhN9oxp/BbdRLgjU81zx8qLEyPODhPMxV4OkcA\n"
+ + "SDwZTSxxAgMBAAGjgaUwgaIwHQYDVR0OBBYEFLOAtr/YrYj9H04EDLA0fd14jisF\n"
+ + "MGMGA1UdIwRcMFqAFLOAtr/YrYj9H04EDLA0fd14jisFoT+kPTA7MQswCQYDVQQG\n"
+ + "EwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2\n"
+ + "Y2WCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEC\n"
+ + "BQADgYEAr8ExpXu/FTIRiMzPm0ubqwME4lniilwQUiEOD/4DbksNjEIcUyS2hIk1\n"
+ + "qsmjJz3SHBnwhxl9dhJVwk2tZLkPGW86Zn0TPVRsttK4inTgCC9GFGeqQBdrU/uf\n"
+ + "lipBzXWljrfbg4N/kK8m2LabtKUMMnGysM8rN0Fx2PYm5xxGvtM=\n"
+ + "-----END CERTIFICATE-----";
// The certificate issued by above trust anchor, signed with MD5
- static String targetCertStr =
- "-----BEGIN CERTIFICATE-----\n" +
- "MIICeDCCAeGgAwIBAgIBAjANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" +
- "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" +
- "MTExMTE4MTExNDA2WhcNMzEwODA1MTExNDA2WjBPMQswCQYDVQQGEwJVUzENMAsG\n" +
- "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxEjAQBgNV\n" +
- "BAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwDnm96mw\n" +
- "fXCH4bgXk1US0VcJsQVxUtGMyncAveMuzBzNzOmKZPeqyYX1Fuh4q+cuza03WTJd\n" +
- "G9nOkNr364e3Rn1aaHjCMcBmFflObnGnhhufNmIGYogJ9dJPmhUVPEVAXrMG+Ces\n" +
- "NKy2E8woGnLMrqu6yiuTClbLBPK8fWzTXrECAwEAAaN4MHYwCwYDVR0PBAQDAgPo\n" +
- "MB0GA1UdDgQWBBSdRrpocLPJXyGfDmMWJrcEf29WGDAfBgNVHSMEGDAWgBSzgLa/\n" +
- "2K2I/R9OBAywNH3deI4rBTAnBgNVHSUEIDAeBggrBgEFBQcDAQYIKwYBBQUHAwIG\n" +
- "CCsGAQUFBwMDMA0GCSqGSIb3DQEBBAUAA4GBAKJ71ZiCUykkJrCLYUxlFlhvUcr9\n" +
- "sTcOc67QdroW5f412NI15SXWDiley/JOasIiuIFPjaJBjOKoHOvTjG/snVu9wEgq\n" +
- "YNR8dPsO+NM8r79C6jO+Jx5fYAC7os2XxS75h3NX0ElJcbwIXGBJ6xRrsFh/BGYH\n" +
- "yvudOlX4BkVR0l1K\n" +
- "-----END CERTIFICATE-----";
+ private static final String TARGET_CERT_STR = "-----BEGIN CERTIFICATE-----\n"
+ + "MIICeDCCAeGgAwIBAgIBAjANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n"
+ + "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n"
+ + "MTExMTE4MTExNDA2WhcNMzEwODA1MTExNDA2WjBPMQswCQYDVQQGEwJVUzENMAsG\n"
+ + "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxEjAQBgNV\n"
+ + "BAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwDnm96mw\n"
+ + "fXCH4bgXk1US0VcJsQVxUtGMyncAveMuzBzNzOmKZPeqyYX1Fuh4q+cuza03WTJd\n"
+ + "G9nOkNr364e3Rn1aaHjCMcBmFflObnGnhhufNmIGYogJ9dJPmhUVPEVAXrMG+Ces\n"
+ + "NKy2E8woGnLMrqu6yiuTClbLBPK8fWzTXrECAwEAAaN4MHYwCwYDVR0PBAQDAgPo\n"
+ + "MB0GA1UdDgQWBBSdRrpocLPJXyGfDmMWJrcEf29WGDAfBgNVHSMEGDAWgBSzgLa/\n"
+ + "2K2I/R9OBAywNH3deI4rBTAnBgNVHSUEIDAeBggrBgEFBQcDAQYIKwYBBQUHAwIG\n"
+ + "CCsGAQUFBwMDMA0GCSqGSIb3DQEBBAUAA4GBAKJ71ZiCUykkJrCLYUxlFlhvUcr9\n"
+ + "sTcOc67QdroW5f412NI15SXWDiley/JOasIiuIFPjaJBjOKoHOvTjG/snVu9wEgq\n"
+ + "YNR8dPsO+NM8r79C6jO+Jx5fYAC7os2XxS75h3NX0ElJcbwIXGBJ6xRrsFh/BGYH\n"
+ + "yvudOlX4BkVR0l1K\n"
+ + "-----END CERTIFICATE-----";
// Private key in the format of PKCS#8.
- static String targetPrivateKey =
- "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMA55vepsH1wh+G4\n" +
- "F5NVEtFXCbEFcVLRjMp3AL3jLswczczpimT3qsmF9RboeKvnLs2tN1kyXRvZzpDa\n" +
- "9+uHt0Z9Wmh4wjHAZhX5Tm5xp4YbnzZiBmKICfXST5oVFTxFQF6zBvgnrDSsthPM\n" +
- "KBpyzK6rusorkwpWywTyvH1s016xAgMBAAECgYEAn9bF3oRkdDoBU0i/mcww5I+K\n" +
- "SH9tFt+WQbiojjz9ac49trkvUfu7MO1Jui2+QbrvaSkyj+HYGFOJd1wMsPXeB7ck\n" +
- "5mOIYV4uZK8jfNMSQ8v0tFEeIPp5lKdw1XnrQfSe+abo2eL5Lwso437Y4s3w37+H\n" +
- "aY3d76hR5qly+Ys+Ww0CQQDjeOoX89d/xhRqGXKjCx8ImE/dPmsI8O27cwtKrDYJ\n" +
- "6t0v/xryVIdvOYcRBvKnqEogOH7T1kI+LnWKUTJ2ehJ7AkEA2FVloPVqCehXcc7e\n" +
- "z3TDpU9w1B0JXklcV5HddYsRqp9RukN/VK4szKE7F1yoarIUtfE9Lr9082Jwyp3M\n" +
- "L11xwwJBAKsZ+Hur3x0tUY29No2Nf/pnFyvEF57SGwA0uPmiL8Ol9lpz+UDudDEl\n" +
- "hIM6Rqv12kwCMuQE9i7vo1o3WU3k5KECQEqhg1L49yD935TqiiFFpe0Ur9btQXse\n" +
- "kdXAA4d2d5zGI7q/aGD9SYU6phkUJSHR16VA2RuUfzMrpb+wmm1IrmMCQFtLoKRT\n" +
- "A5kokFb+E3Gplu29tJvCUpfwgBFRS+wmkvtiaU/tiyDcVgDO+An5DwedxxdVzqiE\n" +
- "njWHoKY3axDQ8OU=\n";
+ private static final String TARGET_PRIV_KEY_STR = "MIICdwIBADANBgkqhkiG9w0B\n"
+ + "AQEFAASCAmEwggJdAgEAAoGBAMA55vepsH1wh+G4F5NVEtFXCbEFcVLRjMp3AL3j\n"
+ + "LswczczpimT3qsmF9RboeKvnLs2tN1kyXRvZzpDa9+uHt0Z9Wmh4wjHAZhX5Tm5x\n"
+ + "p4YbnzZiBmKICfXST5oVFTxFQF6zBvgnrDSsthPMKBpyzK6rusorkwpWywTyvH1s\n"
+ + "016xAgMBAAECgYEAn9bF3oRkdDoBU0i/mcww5I+KSH9tFt+WQbiojjz9ac49trkv\n"
+ + "Ufu7MO1Jui2+QbrvaSkyj+HYGFOJd1wMsPXeB7ck5mOIYV4uZK8jfNMSQ8v0tFEe\n"
+ + "IPp5lKdw1XnrQfSe+abo2eL5Lwso437Y4s3w37+HaY3d76hR5qly+Ys+Ww0CQQDj\n"
+ + "eOoX89d/xhRqGXKjCx8ImE/dPmsI8O27cwtKrDYJ6t0v/xryVIdvOYcRBvKnqEog\n"
+ + "OH7T1kI+LnWKUTJ2ehJ7AkEA2FVloPVqCehXcc7ez3TDpU9w1B0JXklcV5HddYsR\n"
+ + "qp9RukN/VK4szKE7F1yoarIUtfE9Lr9082Jwyp3ML11xwwJBAKsZ+Hur3x0tUY29\n"
+ + "No2Nf/pnFyvEF57SGwA0uPmiL8Ol9lpz+UDudDElhIM6Rqv12kwCMuQE9i7vo1o3\n"
+ + "WU3k5KECQEqhg1L49yD935TqiiFFpe0Ur9btQXsekdXAA4d2d5zGI7q/aGD9SYU6\n"
+ + "phkUJSHR16VA2RuUfzMrpb+wmm1IrmMCQFtLoKRTA5kokFb+E3Gplu29tJvCUpfw\n"
+ + "gBFRS+wmkvtiaU/tiyDcVgDO+An5DwedxxdVzqiEnjWHoKY3axDQ8OU=";
-
- static char passphrase[] = "passphrase".toCharArray();
+ private static final char PASSPHRASE[] = "passphrase".toCharArray();
/*
* Is the server ready to serve?
*/
- volatile static boolean serverReady = false;
+ private static volatile CountDownLatch sync = new CountDownLatch(1);
/*
* Turn on SSL debugging?
*/
- static boolean debug = false;
+ private static final boolean DEBUG = false;
/*
* Define the server side of the test.
@@ -144,29 +126,30 @@
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
- void doServerSide() throws Exception {
- SSLContext context = generateSSLContext(trustedCertStr, targetCertStr,
- targetPrivateKey);
+ private void doServerSide() throws Exception {
+ SSLContext context = generateSSLContext(TRUSTED_CERT_STR, TARGET_CERT_STR,
+ TARGET_PRIV_KEY_STR);
SSLServerSocketFactory sslssf = context.getServerSocketFactory();
- SSLServerSocket sslServerSocket =
- (SSLServerSocket)sslssf.createServerSocket(serverPort);
- sslServerSocket.setNeedClientAuth(true);
- serverPort = sslServerSocket.getLocalPort();
+ try (SSLServerSocket sslServerSocket
+ = (SSLServerSocket) sslssf.createServerSocket(serverPort)) {
+ sslServerSocket.setNeedClientAuth(true);
+ serverPort = sslServerSocket.getLocalPort();
+ /*
+ * Signal Client, we're ready for his connect.
+ */
+ System.out.println("Signal server ready");
+ sync.countDown();
- /*
- * Signal Client, we're ready for his connect.
- */
- serverReady = true;
+ System.out.println("Waiting for client connection");
+ try (SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept()) {
+ InputStream sslIS = sslSocket.getInputStream();
+ OutputStream sslOS = sslSocket.getOutputStream();
- SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept();
- InputStream sslIS = sslSocket.getInputStream();
- OutputStream sslOS = sslSocket.getOutputStream();
-
- sslIS.read();
- sslOS.write('A');
- sslOS.flush();
-
- sslSocket.close();
+ sslIS.read();
+ sslOS.write('A');
+ sslOS.flush();
+ }
+ }
}
/*
@@ -175,33 +158,31 @@
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
- void doClientSide() throws Exception {
+ private void doClientSide() throws Exception {
/*
* Wait for server to get started.
*/
- while (!serverReady) {
- Thread.sleep(50);
- }
+ System.out.println("Waiting for server ready");
+ sync.await();
- SSLContext context = generateSSLContext(trustedCertStr, targetCertStr,
- targetPrivateKey);
+ SSLContext context = generateSSLContext(TRUSTED_CERT_STR, TARGET_CERT_STR,
+ TARGET_PRIV_KEY_STR);
SSLSocketFactory sslsf = context.getSocketFactory();
- SSLSocket sslSocket =
- (SSLSocket)sslsf.createSocket("localhost", serverPort);
-
- // enable the specified TLS protocol
- sslSocket.setEnabledProtocols(new String[] {tlsProtocol});
+ System.out.println("Connect to server on port: " + serverPort);
+ try (SSLSocket sslSocket
+ = (SSLSocket) sslsf.createSocket("localhost", serverPort)) {
+ // enable the specified TLS protocol
+ sslSocket.setEnabledProtocols(new String[]{tlsProtocol});
- InputStream sslIS = sslSocket.getInputStream();
- OutputStream sslOS = sslSocket.getOutputStream();
+ InputStream sslIS = sslSocket.getInputStream();
+ OutputStream sslOS = sslSocket.getOutputStream();
- sslOS.write('B');
- sslOS.flush();
- sslIS.read();
-
- sslSocket.close();
+ sslOS.write('B');
+ sslOS.flush();
+ sslIS.read();
+ }
}
/*
@@ -240,10 +221,10 @@
if (keyCertStr != null) {
// generate the private key.
PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(
- Base64.getMimeDecoder().decode(keySpecStr));
+ Base64.getMimeDecoder().decode(keySpecStr));
KeyFactory kf = KeyFactory.getInstance("RSA");
- RSAPrivateKey priKey =
- (RSAPrivateKey)kf.generatePrivate(priKeySpec);
+ RSAPrivateKey priKey
+ = (RSAPrivateKey) kf.generatePrivate(priKeySpec);
// generate certificate chain
is = new ByteArrayInputStream(keyCertStr.getBytes());
@@ -257,7 +238,7 @@
chain[0] = keyCert;
// import the key entry.
- ks.setKeyEntry("Whatever", priKey, passphrase, chain);
+ ks.setKeyEntry("Whatever", priKey, PASSPHRASE, chain);
}
// create SSL context
@@ -267,7 +248,7 @@
SSLContext ctx = SSLContext.getInstance(tlsProtocol);
if (keyCertStr != null && !keyCertStr.isEmpty()) {
KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");
- kmf.init(ks, passphrase);
+ kmf.init(ks, PASSPHRASE);
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
ks = null;
@@ -278,12 +259,10 @@
return ctx;
}
+ // use any free port by default
+ private volatile int serverPort = 0;
- // use any free port by default
- volatile int serverPort = 0;
-
- volatile Exception serverException = null;
- volatile Exception clientException = null;
+ private volatile Exception serverException = null;
public static void main(String[] args) throws Exception {
// MD5 is used in this test case, don't disable MD5 algorithm.
@@ -292,140 +271,61 @@
Security.setProperty("jdk.tls.disabledAlgorithms",
"SSLv3, RC4, DH keySize < 768");
- if (debug)
+ if (DEBUG) {
System.setProperty("javax.net.debug", "all");
+ }
/*
* Get the customized arguments.
*/
parseArguments(args);
-
/*
* Start the tests.
*/
- new MD2InTrustAnchor();
+ new MD2InTrustAnchor().runTest();
}
- Thread clientThread = null;
- Thread serverThread = null;
+ private Thread serverThread = null;
/*
- * Primary constructor, used to drive remainder of the test.
+ * Used to drive remainder of the test.
*
* Fork off the other side, then do your work.
*/
- MD2InTrustAnchor() throws Exception {
- try {
- if (separateServerThread) {
- startServer(true);
- startClient(false);
- } else {
- startClient(true);
- startServer(false);
- }
- } catch (Exception e) {
- // swallow for now. Show later
- }
+ public void runTest() throws Exception {
+ startServerThread();
+ doClientSide();
/*
* Wait for other side to close down.
*/
- if (separateServerThread) {
- serverThread.join();
- } else {
- clientThread.join();
- }
-
- /*
- * When we get here, the test is pretty much over.
- * Which side threw the error?
- */
- Exception local;
- Exception remote;
- String whichRemote;
+ serverThread.join();
- if (separateServerThread) {
- remote = serverException;
- local = clientException;
- whichRemote = "server";
- } else {
- remote = clientException;
- local = serverException;
- whichRemote = "client";
- }
-
- /*
- * If both failed, return the curthread's exception, but also
- * print the remote side Exception
- */
- if ((local != null) && (remote != null)) {
- System.out.println(whichRemote + " also threw:");
- remote.printStackTrace();
- System.out.println();
- throw local;
- }
-
- if (remote != null) {
- throw remote;
- }
-
- if (local != null) {
- throw local;
+ if (serverException != null) {
+ throw serverException;
}
}
- void startServer(boolean newThread) throws Exception {
- if (newThread) {
- serverThread = new Thread() {
- public void run() {
- try {
- doServerSide();
- } catch (Exception e) {
- /*
- * Our server thread just died.
- *
- * Release the client, if not active already...
- */
- System.err.println("Server died...");
- serverReady = true;
- serverException = e;
- }
+ private void startServerThread() {
+ serverThread = new Thread() {
+ @Override
+ public void run() {
+ try {
+ doServerSide();
+ } catch (Exception e) {
+ /*
+ * Our server thread just died.
+ *
+ * Release the client, if not active already...
+ */
+ System.err.println("Server died...");
+ e.printStackTrace(System.out);
+ serverException = e;
+ sync.countDown();
}
- };
- serverThread.start();
- } else {
- try {
- doServerSide();
- } catch (Exception e) {
- serverException = e;
- } finally {
- serverReady = true;
}
- }
- }
+ };
- void startClient(boolean newThread) throws Exception {
- if (newThread) {
- clientThread = new Thread() {
- public void run() {
- try {
- doClientSide();
- } catch (Exception e) {
- /*
- * Our client thread just died.
- */
- System.err.println("Client died...");
- clientException = e;
- }
- }
- };
- clientThread.start();
- } else {
- try {
- doClientSide();
- } catch (Exception e) {
- clientException = e;
- }
- }
+ serverThread.start();
}
}
--- a/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m1/p1/Main.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m1/p1/Main.java Thu Apr 21 13:37:31 2016 -0700
@@ -29,6 +29,7 @@
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.util.Collections;
import java.util.Set;
public class Main {
@@ -40,7 +41,8 @@
validate(Main.class.getModule().getDescriptor());
// read m1/module-info.class
- FileSystem fs = FileSystems.newFileSystem(URI.create("jrt:/"), null);
+ FileSystem fs = FileSystems.newFileSystem(URI.create("jrt:/"),
+ Collections.emptyMap());
Path path = fs.getPath("/", "modules", "m1", "module-info.class");
validate(ModuleDescriptor.read(Files.newInputStream(path)));
}
--- a/jdk/test/tools/launcher/Arrrghs.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/tools/launcher/Arrrghs.java Thu Apr 21 13:37:31 2016 -0700
@@ -489,7 +489,7 @@
return;
}
- TestResult tr = null;
+ TestResult tr;
// a missing class
createJar("MIA", new File("some.jar"), new File("Foo"),
@@ -592,7 +592,7 @@
if (!isEnglishLocale()) { // only english version
return;
}
- TestResult tr = null;
+ TestResult tr;
// a missing class
createJar("MIA", new File("some.jar"), new File("Foo"),
(String[])null);
--- a/jdk/test/tools/launcher/DefaultLocaleTestRun.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/tools/launcher/DefaultLocaleTestRun.java Thu Apr 21 13:37:31 2016 -0700
@@ -41,7 +41,7 @@
System.out.println("Test passes vacuously on non-windows");
return;
}
- TestResult tr = null;
+ TestResult tr;
tr = doExec(javaCmd,
"-cp", TEST_CLASSES_DIR.getAbsolutePath(),
"DefaultLocaleTest", "-w", "x.out");
--- a/jdk/test/tools/launcher/ExecutionEnvironment.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/tools/launcher/ExecutionEnvironment.java Thu Apr 21 13:37:31 2016 -0700
@@ -120,15 +120,14 @@
*/
@Test
void testEcoFriendly() {
- TestResult tr = null;
-
Map<String, String> env = new HashMap<>();
for (String x : LD_PATH_STRINGS) {
String pairs[] = x.split("=");
env.put(pairs[0], pairs[1]);
}
- tr = doExec(env, javaCmd, "-jar", testJarFile.getAbsolutePath());
+ TestResult tr =
+ doExec(env, javaCmd, "-jar", testJarFile.getAbsolutePath());
if (!tr.isNotZeroOutput()) {
flagError(tr, "Error: No output at all. Did the test execute ?");
@@ -180,7 +179,7 @@
*/
@Test
void testJavaLibraryPath() {
- TestResult tr = null;
+ TestResult tr;
Map<String, String> env = new HashMap<>();
@@ -240,17 +239,14 @@
*/
@Test
void testVmSelection() {
-
- TestResult tr = null;
-
if (haveClientVM) {
- tr = doExec(javaCmd, "-client", "-version");
+ TestResult tr = doExec(javaCmd, "-client", "-version");
if (!tr.matches(".*Client VM.*")) {
flagError(tr, "the expected vm -client did not launch");
}
}
if (haveServerVM) {
- tr = doExec(javaCmd, "-server", "-version");
+ TestResult tr = doExec(javaCmd, "-server", "-version");
if (!tr.matches(".*Server VM.*")) {
flagError(tr, "the expected vm -server did not launch");
}
--- a/jdk/test/tools/launcher/FXLauncherTest.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/tools/launcher/FXLauncherTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -239,7 +239,7 @@
createFile(ManifestFile, createManifestContents(StdMainClass, fxMC));
createJar(FXtestJar, ManifestFile);
String sTestJar = FXtestJar.getAbsolutePath();
- TestResult tr;
+ final TestResult tr;
if (useCP) {
tr = doExec(javaCmd, "-cp", sTestJar, StdMainClass, APP_PARMS[0], APP_PARMS[1]);
} else {
@@ -290,7 +290,7 @@
createFile(ManifestFile, createManifestContents(ExtMainClass, fxMC));
createJar(FXtestJar, ManifestFile);
String sTestJar = FXtestJar.getAbsolutePath();
- TestResult tr;
+ final TestResult tr;
if (useCP) {
tr = doExec(javaCmd, "-cp", sTestJar, ExtMainClass, APP_PARMS[0], APP_PARMS[1]);
} else {
@@ -359,7 +359,7 @@
createFile(ManifestFile, createManifestContents(NonFXMainClass, null));
createJar(FXtestJar, ManifestFile);
String sTestJar = FXtestJar.getAbsolutePath();
- TestResult tr;
+ final TestResult tr;
if (useCP) {
tr = doExec(javaCmd, "-verbose:class", "-cp", sTestJar, NonFXMainClass, APP_PARMS[0], APP_PARMS[1]);
--- a/jdk/test/tools/launcher/I18NTest.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/tools/launcher/I18NTest.java Thu Apr 21 13:37:31 2016 -0700
@@ -60,7 +60,7 @@
// compile the generate code using the javac compiler vs. the api, to
// as a bonus point to see if the argument is passed correctly
- TestResult tr = null;
+ TestResult tr;
tr = doExec(javacCmd, fileName + JAVA_FILE_EXT);
if (!tr.isOK()) {
System.out.println(tr);
--- a/jdk/test/tools/launcher/MiscTests.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/tools/launcher/MiscTests.java Thu Apr 21 13:37:31 2016 -0700
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 6856415 8154212
+ * @bug 6856415 8154212 8154470
* @summary Miscellaneous tests, Exceptions
* @compile -XDignore.symbol.file MiscTests.java
* @run main MiscTests
@@ -95,30 +95,34 @@
TestResult tr = doExec(javaCmd,
"-Djava.security.manager", "-jar", testJar.getName(), "foo.bak");
- for (String s : tr.testOutput) {
- System.out.println(s);
- }
if (!tr.contains("java.security.AccessControlException:" +
" access denied (\"java.lang.RuntimePermission\"" +
" \"accessClassInPackage.sun.security.pkcs11\")")) {
- System.out.println(tr.status);
+ System.out.println(tr);
}
}
- static void testJLDEnvWithTool() {
- final Map<String, String> envMap = new HashMap<>();
- envMap.put("_JAVA_LAUNCHER_DEBUG", "true");
- TestResult tr = doExec(envMap, javacCmd, "-version");
- tr.checkPositive();
- if (!tr.isOK()) {
- System.out.println(tr);
+ static void testJLDEnv() {
+ final Map<String, String> envToSet = new HashMap<>();
+ envToSet.put("_JAVA_LAUNCHER_DEBUG", "true");
+ for (String cmd : new String[] { javaCmd, javacCmd }) {
+ TestResult tr = doExec(envToSet, cmd, "-version");
+ tr.checkPositive();
+ String javargs = cmd.equals(javacCmd) ? "on" : "off";
+ String progname = cmd.equals(javacCmd) ? "javac" : "java";
+ if (!tr.isOK()
+ || !tr.matches("\\s*debug:on$")
+ || !tr.matches("\\s*javargs:" + javargs + "$")
+ || !tr.matches("\\s*program name:" + progname + "$")) {
+ System.out.println(tr);
+ }
}
}
public static void main(String... args) throws IOException {
testWithClassPathSetViaProperty();
test6856415();
- testJLDEnvWithTool();
+ testJLDEnv();
if (testExitValue != 0) {
throw new Error(testExitValue + " tests failed");
}
--- a/jdk/test/tools/launcher/Settings.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/tools/launcher/Settings.java Thu Apr 21 13:37:31 2016 -0700
@@ -55,9 +55,9 @@
}
}
- static void checkNoContains(TestResult tr, String str) {
- if (tr.contains(str)) {
- System.out.println(tr.status);
+ static void checkNotContains(TestResult tr, String str) {
+ if (!tr.notContains(str)) {
+ System.out.println(tr);
throw new RuntimeException(str + " found");
}
}
@@ -77,84 +77,77 @@
if (getArch().equals("ppc64") || getArch().equals("ppc64le")) {
stackSize = "800";
}
- TestResult tr = null;
+ TestResult tr;
tr = doExec(javaCmd, "-Xms64m", "-Xmx512m",
"-Xss" + stackSize + "k", "-XshowSettings", "-jar", testJar.getAbsolutePath());
containsAllOptions(tr);
if (!tr.isOK()) {
- System.out.println(tr.status);
+ System.out.println(tr);
throw new RuntimeException("test fails");
}
tr = doExec(javaCmd, "-Xms65536k", "-Xmx712m",
"-Xss" + stackSize + "000", "-XshowSettings", "-jar", testJar.getAbsolutePath());
containsAllOptions(tr);
if (!tr.isOK()) {
- System.out.println(tr.status);
+ System.out.println(tr);
throw new RuntimeException("test fails");
}
}
static void runTestOptionAll() throws IOException {
init();
- TestResult tr = null;
- tr = doExec(javaCmd, "-XshowSettings:all");
+ TestResult tr = doExec(javaCmd, "-XshowSettings:all");
containsAllOptions(tr);
}
static void runTestOptionVM() throws IOException {
- TestResult tr = null;
- tr = doExec(javaCmd, "-XshowSettings:vm");
+ TestResult tr = doExec(javaCmd, "-XshowSettings:vm");
checkContains(tr, VM_SETTINGS);
- checkNoContains(tr, PROP_SETTINGS);
- checkNoContains(tr, LOCALE_SETTINGS);
+ checkNotContains(tr, PROP_SETTINGS);
+ checkNotContains(tr, LOCALE_SETTINGS);
}
static void runTestOptionProperty() throws IOException {
- TestResult tr = null;
- tr = doExec(javaCmd, "-XshowSettings:properties");
- checkNoContains(tr, VM_SETTINGS);
+ TestResult tr = doExec(javaCmd, "-XshowSettings:properties");
+ checkNotContains(tr, VM_SETTINGS);
checkContains(tr, PROP_SETTINGS);
- checkNoContains(tr, LOCALE_SETTINGS);
+ checkNotContains(tr, LOCALE_SETTINGS);
}
static void runTestOptionLocale() throws IOException {
- TestResult tr = null;
- tr = doExec(javaCmd, "-XshowSettings:locale");
- checkNoContains(tr, VM_SETTINGS);
- checkNoContains(tr, PROP_SETTINGS);
+ TestResult tr = doExec(javaCmd, "-XshowSettings:locale");
+ checkNotContains(tr, VM_SETTINGS);
+ checkNotContains(tr, PROP_SETTINGS);
checkContains(tr, LOCALE_SETTINGS);
}
static void runTestBadOptions() throws IOException {
- TestResult tr = null;
- tr = doExec(javaCmd, "-XshowSettingsBadOption");
- checkNoContains(tr, VM_SETTINGS);
- checkNoContains(tr, PROP_SETTINGS);
- checkNoContains(tr, LOCALE_SETTINGS);
+ TestResult tr = doExec(javaCmd, "-XshowSettingsBadOption");
+ checkNotContains(tr, VM_SETTINGS);
+ checkNotContains(tr, PROP_SETTINGS);
+ checkNotContains(tr, LOCALE_SETTINGS);
checkContains(tr, "Unrecognized option: -XshowSettingsBadOption");
}
static void runTest7123582() throws IOException {
- TestResult tr = null;
- tr = doExec(javaCmd, "-XshowSettings", "-version");
+ TestResult tr = doExec(javaCmd, "-XshowSettings", "-version");
if (!tr.isOK()) {
- System.out.println(tr.status);
+ System.out.println(tr);
throw new RuntimeException("test fails");
}
containsAllOptions(tr);
}
- public static void main(String... args) {
- try {
- runTestOptionAll();
- runTestOptionDefault();
- runTestOptionVM();
- runTestOptionProperty();
- runTestOptionLocale();
- runTestBadOptions();
- runTest7123582();
- } catch (IOException ioe) {
- throw new RuntimeException(ioe);
+ public static void main(String... args) throws IOException {
+ runTestOptionAll();
+ runTestOptionDefault();
+ runTestOptionVM();
+ runTestOptionProperty();
+ runTestOptionLocale();
+ runTestBadOptions();
+ runTest7123582();
+ if (testExitValue != 0) {
+ throw new Error(testExitValue + " tests failed");
}
}
}
--- a/jdk/test/tools/launcher/TestHelper.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/tools/launcher/TestHelper.java Thu Apr 21 13:37:31 2016 -0700
@@ -603,23 +603,23 @@
return true;
}
- boolean matches(String stringToMatch) {
+ boolean matches(String regexToMatch) {
for (String x : testOutput) {
- if (x.matches(stringToMatch)) {
+ if (x.matches(regexToMatch)) {
return true;
}
}
- appendError("string <" + stringToMatch + "> not found");
+ appendError("regex <" + regexToMatch + "> not matched");
return false;
}
- boolean notMatches(String stringToMatch) {
+ boolean notMatches(String regexToMatch) {
for (String x : testOutput) {
- if (!x.matches(stringToMatch)) {
+ if (!x.matches(regexToMatch)) {
return true;
}
}
- appendError("string <" + stringToMatch + "> found");
+ appendError("regex <" + regexToMatch + "> matched");
return false;
}
}
--- a/jdk/test/tools/launcher/TestSpecialArgs.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/tools/launcher/TestSpecialArgs.java Thu Apr 21 13:37:31 2016 -0700
@@ -241,7 +241,7 @@
@Test
void testNMArgumentProcessing() throws FileNotFoundException {
- TestResult tr = null;
+ TestResult tr;
// the direct invokers of the VM
String options[] = {
"-version", "-fullversion", "-help", "-?", "-X"
--- a/jdk/test/tools/launcher/TooSmallStackSize.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/tools/launcher/TooSmallStackSize.java Thu Apr 21 13:37:31 2016 -0700
@@ -85,11 +85,10 @@
*/
static String checkStack(String stackSize) {
String min_stack_allowed;
- TestResult tr;
if (verbose)
System.out.println("*** Testing " + stackSize);
- tr = doExec(javaCmd, "-Xss" + stackSize, "-version");
+ TestResult tr = doExec(javaCmd, "-Xss" + stackSize, "-version");
if (verbose)
printTestOutput(tr);
@@ -114,11 +113,9 @@
* Run the JVM with the minimum allowed stack size. This should always succeed.
*/
static void checkMinStackAllowed(String stackSize) {
- TestResult tr = null;
-
if (verbose)
System.out.println("*** Testing " + stackSize);
- tr = doExec(javaCmd, "-Xss" + stackSize, "-version");
+ TestResult tr = doExec(javaCmd, "-Xss" + stackSize, "-version");
if (verbose)
printTestOutput(tr);
--- a/jdk/test/tools/launcher/ToolsOpts.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/tools/launcher/ToolsOpts.java Thu Apr 21 13:37:31 2016 -0700
@@ -149,7 +149,7 @@
*/
static void runTestOptions() throws IOException {
init();
- TestResult tr = null;
+ TestResult tr;
int jpos = -1;
for (String arg[] : optionPatterns) {
jpos = indexOfJoption(arg);
--- a/jdk/test/tools/launcher/VersionCheck.java Thu Apr 21 12:57:11 2016 -0700
+++ b/jdk/test/tools/launcher/VersionCheck.java Thu Apr 21 13:37:31 2016 -0700
@@ -151,12 +151,11 @@
* of the -version output as they are inconsistent.
*/
static boolean testToolVersion() {
- TestResult tr = null;
TestHelper.testExitValue = 0;
for (File f : new File(JAVA_BIN).listFiles(new ToolFilter(BLACKLIST_VERSION))) {
String x = f.getAbsolutePath();
System.out.println("Testing (-version): " + x);
- tr = doExec(x, "-version");
+ TestResult tr = doExec(x, "-version");
tr.checkPositive();
}
return TestHelper.testExitValue == 0;